TCP客户端断线重连-升级版

解决拔掉网线后无法快速诊断是否掉线问题

using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System;
using System.Text;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using System.Threading;

namespace MyTcpClient
{
    //规范命名、添加注释、合理封装、限制访问权限    
    public class AsyncTcpClient
    {
        private string ip1;
        private int port1;
        private byte[] ReadBytes = new byte[1024];
        //单例
        private TcpClient tcpClient;
        //连接服务器
        public void ConnectServer(string ip, int port)
        {
            //防止多个事例去重复连接
            if (isTryingToCon == true)
            {
                return;
            }
            ip1 = ip;
            port1 = port;
            try
            {
                if (tcpClient != null)
                {
                    tcpClient.Close();
                }
                tcpClient = new TcpClient();
                isTryingToCon = true;
                //开始异步
                tcpClient.BeginConnect(IPAddress.Parse(ip), port, Lianjie, null);
            }
            catch (Exception e)
            {
            }
        }
        private bool isTryingToCon = false;
        //连接判断
        private void Lianjie(IAsyncResult ar)
        {
            if (IsClose)
            {
                return;
            }
            try
            {
                if (tcpClient.Connected == false)
                {
                    SetCon(0);
                    tcpClient.Close();
                    tcpClient = new System.Net.Sockets.TcpClient();
                    //尝试重连。。。。。。;
                    tcpClient.BeginConnect(IPAddress.Parse(ip1), port1, Lianjie, null);
                }
                else
                {
                    tcpClient.Client.IOControl(IOControlCode.KeepAliveValues, KeepAlive(1, 500, 500), null);
                    //连接上了
                    isTryingToCon = false;
                    //结束异步连接
                    tcpClient.EndConnect(ar);
                    //读取数据
                    tcpClient.GetStream().BeginRead(ReadBytes, 0, ReadBytes.Length, ReceiveCallBack, null);
                    SetCon(1);
                }
            }
            catch (Exception)
            {
            }
        }
        private byte[] KeepAlive(int onOff, int keepAliveTime, int keepAliveInterval)
        {
            byte[] buffer = new byte[12];
            BitConverter.GetBytes(onOff).CopyTo(buffer, 0);
            BitConverter.GetBytes(keepAliveTime).CopyTo(buffer, 4);
            BitConverter.GetBytes(keepAliveInterval).CopyTo(buffer, 8);
            return buffer;
        }

        //接收消息
        private void ReceiveCallBack(IAsyncResult ar)
        {
            try
            {
                int len = tcpClient.GetStream().EndRead(ar);//结束异步读取
                if (len > 0)
                {
                    MyEventArgs e = new MyEventArgs(ip1, ReadBytes);
                    _MsgChange(e);
                    //重置数据,防止旧数据残留
                    ReadBytes = new byte[512];
                    tcpClient.GetStream().BeginRead(ReadBytes, 0, ReadBytes.Length, ReceiveCallBack, null);
                }
                else
                {
                    //尝试重连。。。。。。"
                    ConnectServer(ip1, port1);
                }
            }
            catch (Exception e)
            {
            }
        }

        //发送消息
        public bool SendMsg(string msg)
        {
            //发送XXXX0001_000000000000_   (没有下划线)             
            //接收00570002_000000000000_010001020103
            try
            {
                //数据部分
                byte[] bt_Data = Encoding.ASCII.GetBytes(msg);
                byte[] bt_head = Encoding.ASCII.GetBytes((bt_Data.Length + 4).ToString("0000"));
                byte[] bt_send = new byte[bt_Data.Length + 4];
                for (int i = 0; i < bt_head.Length; i++)
                {
                    bt_send[i] = bt_head[i];
                }
                for (int i = 0; i < bt_Data.Length; i++)
                {
                    bt_send[i + 4] = bt_Data[i];
                }
                //开始异步发送
                try
                {
                    tcpClient.GetStream().BeginWrite(bt_send, 0, bt_send.Length, (ar) =>
                    {
                        tcpClient.GetStream().EndWrite(ar);//结束异步发送
                    }, null);
                }
                catch (Exception ex)
                {
                    string abc = ex.ToString();
                }

                return true;
            }
            catch (Exception ex)
            {
                SetCon(-1);
                SetCon(0);
                // int a = ex.NativeErrorCode;
                //尝试重连。。。。。。"
                ConnectServer(ip1, port1);
                return false;
            }
        }
        public bool SendMsg(byte[] msg)
        {
            try
            {
                //开始异步发送
                tcpClient.GetStream().BeginWrite(msg, 0, msg.Length, (ar) =>
                {
                    tcpClient.GetStream().EndWrite(ar);//结束异步发送
                }, null);
                return true;
            }
            catch (Exception ex)
            {
                //尝试重连。。。。。。"
                SetCon(-1);
                SetCon(0);
                ConnectServer(ip1, port1);
                return false;
            }
        }
        bool IsClose = false;
        /// <summary>
        /// 断开连接
        /// </summary>
        public void Close()
        {
            IsClose = true;
            if (tcpClient != null && (tcpClient.Client == null || tcpClient.Client.Connected))
            {
                tcpClient.Close();
            }
        }
        public int isConnected = -1;
        /// <summary>
        /// -1 初始化  0 未连接  1 连接
        /// </summary>
        /// <param name="_con"></param>
        private void SetCon(int _con)
        {
            if (isConnected != _con)
            {
                bool rel = false;
                if (_con == 1)
                {
                    rel = true;
                }
                isConnected = _con;
                MyEventArgs e = new MyEventArgs(ip1 + "__" + port1.ToString(), rel);
                _ConChange(e);
            }
        }
        public void StarPing()
        {
            Task.Factory.StartNew(() => PingOC());
        }
        private void PingOC()
        {
            Ping ping = new Ping();
            while (!IsClose)
            {
                try
                {
                    PingReply pingReply = ping.Send(ip1, 1000);
                    //网络状态
                    if (pingReply.Status != IPStatus.Success)
                    {
                        SetCon(-1);
                        SetCon(0);
                        ConnectServer(ip1, port1);
                    }
                    Thread.Sleep(1000);
                }
                catch (Exception)
                {

                }
            }
        }

        public class MyEventArgs : EventArgs
        {
            public string IP;
            public bool IsConnetct;
            public byte[] Msg;
            public MyEventArgs(string iP, byte[] msg)
            {
                IP = iP;
                Msg = msg;
            }
            public MyEventArgs(string iP, bool iscon)
            {
                IP = iP;
                IsConnetct = iscon;
            }
        }
        //连接状态
        public delegate void ConChange(object sender, MyEventArgs args);
        public event ConChange OnConChange;
        protected virtual void _ConChange(MyEventArgs e)
        {
            if (OnConChange != null)
            {
                OnConChange(this, e);
            }
        }
        //收到的消息
        public delegate void MsgChange(object sender, MyEventArgs args);
        public event MsgChange OnMsgChange;
        protected virtual void _MsgChange(MyEventArgs e)
        {
            if (OnMsgChange != null)
            {
                OnMsgChange(this, e);
            }
        }
    }
}

调用方法:

 AsyncTcpClient sw = new AsyncTcpClient();           
 sw.ConnectServer("192.168.1.1", 4545);
 sw.OnConChange += Sw_OnConChange;
 sw.OnMsgChange += Sw_OnMsgChange;
 sw.StarPing();

 private void Sw_OnConChange(object sender, AsyncTcpClient.MyEventArgs args)
 {
    if (args.IsConnetct)
    {
        //已连接
    }
    else
    {
        //已断开
    }
}

 private void Sw_OnMsgChange(object sender, AsyncTcpClient.MyEventArgs args)
  {
        //接收的信息
        string str = Encoding.ASCII.GetString(args.Msg, 0, args.Msg.Length);
        str = Uri.UnescapeDataString(str).Replace("\0", "");
   }

        public void CloseTcp()
        {
            sw.OnConChange -= Sw_OnConChange;
            sw.OnMsgChange -= Sw_OnMsgChange;
            sw.Close();
        }

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fanwenhu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值