C#Socket客戶端自動重連服務端

本文探讨了C#中实现自动重连的策略,详细介绍了通过专用通讯类和线程来实现实时连接和消息发送的过程。面对服务端断开后的重连挑战,博主分享了遇到的问题及尝试的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

關於C#的自動重連,我是初次嘗試,試驗的情況就一種,比如服務端軟件關閉了,客戶端會開啟實時連接,只要服務端開啟偵聽,客戶端便能直接連接上,讓後發送認證信息,通知當前上線的客戶端身份。
以下是我自動重連的主要代碼:
代碼一:通訊專用類,為了方便管理和調用通訊參數,我把所有的通訊參數寫在下面的類中
/// <summary>
    /// 通訊專用類
    /// </summary>
    public class CommunicateInfo
    {
        #region 通訊專用參數
        /// <summary>
        /// 發送信息專用字典
        /// </summary>
        public Dictionary<string, byte[]> Dic_SendMsg = new Dictionary<string, byte[]>();
        /// <summary>
        /// 消息發送專用隊列
        /// </summary>
        public Queue Q_MsgSend = new Queue();
        /// <summary>
        /// 通訊線程
        /// </summary>
        public Thread th_Socket;
        /// <summary>
        /// 通訊專用套接字
        /// </summary>
        public Socket soc_client;
        /// <summary>
        /// 心跳發送統計,收到回復清零,大於3次,認為斷線
        /// </summary>
        public int heartcount = 0;
        /// <summary>
        /// 對接能否放料盤
        /// </summary>
        public bool putplate = false;
        /// <summary>
        /// 對接能否取料盤
        /// </summary>
        public bool takeplate = false;
        /// <summary>
        /// 通知流水线取放料盘成功指令
        /// </summary>
        public bool infosuccess;
        /// <summary>
        /// 流水線是否完成交換
        /// </summary>
        public bool exchangeexit = false;
        /// <summary>
        /// 是否啟動入庫
        /// </summary>
        public bool startinput = false;
        /// <summary>
        /// 是否與服務端連接成功
        /// </summary>
        public bool IsConnected = false;
        /// <summary>
        /// 服務端(流水線)ip
        /// </summary>
        public string ser_ip;
        /// <summary>
        /// 服務端端口號
        /// </summary>
        public string ser_port;
        /// <summary>
        /// 當前入料料盤編號
        /// </summary>
        public string inplatenum;
        #endregion
    }

代碼2:自動重連,和消息發送寫在了線程中,避免對UI線程的阻塞,測試中發現,服務端停止監聽后,客戶端三次沒有收到回復,會認為服務端掉線,將連接斷開,重新連接服務端。但是把服務端軟件關閉后,在執行到Socket的Connect()方法時,還是造成了UI的假死,因為該方法執行失敗時,客戶端會持續嘗試一定次數,導致需要一定時間才會跳出該方法。目前我嘗試了多種方法,比如說異步的Connect,Application.DoEvent(),延時等都沒有很好的解決該問題,網友大神有好的辦法可以指導一下


//實例化通訊類
CommunicateInfo cominfo=new CommunicateInfo();
 /// <summary>
        /// 通訊專用線程,實時連接服務端,實時接收數據
        /// </summary>
        public void CommunicateThread()
        {
            while (true)
            {
                try
                {
                    this.Invoke((MethodInvoker)delegate
                {
                    Application.DoEvents();
                    //Thread.Sleep(TimeSpan.FromMilliseconds(3000));
                    //return;
                    #region 自動連接
                    if (!cominfo.IsConnected)
                    {
                        //初次連接與後期自動重連
                        cominfo.soc_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        //cominfo.soc_client.
                        //cominfo.soc_client.
                        IPAddress server_ip = IPAddress.Parse(cominfo.ser_ip);
                        IPEndPoint poit = new IPEndPoint(server_ip, Int32.Parse(cominfo.ser_port));
                        Thread.Sleep(TimeSpan.FromMilliseconds(1));
                        try
                        {
                            //cominfo.soc_client.BeginConnect(cominfo.ser_ip,Int32.Parse( cominfo.ser_port), new AsyncCallback(ConnectCallback1), cominfo.soc_client);
                            
                            cominfo.soc_client.Connect(server_ip, Int32.Parse(cominfo.ser_port));
                            //allDone.WaitOne();
                            //Application.DoEvents();
                        }
                        catch (Exception ex)
                        {
                        //連接失敗后釋放該資源
                            cominfo.soc_client.Close();
                            //cominfo.soc_client.Disconnect(true);

                            //cominfo.soc_client.Dispose();
                            return;
                            //throw;
                        }
                        //等待3s再啟動連接
                        //Thread.Sleep(TimeSpan.FromSeconds(5));
                        if (cominfo.soc_client.Connected)
                        {
                            cominfo.IsConnected = true;
                            //發送堆垛機編號認證
                            cominfo.soc_client.Send(assembly.BT_ConnectServer("0" + Stacknum[1].ToString()));
                            //心跳發送啟動
                            tm_heart.Interval = 3000;
                            tm_heart.Start();
                        }
                    }
                    #endregion
                    else
                    {
                        byte[] Rec = null;
                        string txtMsg = "";
                        //獲取端口可用數據長度
                        int recLen = cominfo.soc_client.Available;
                        if (recLen > 0)
                        {
                            Rec = new byte[recLen];
                            cominfo.soc_client.Receive(Rec);
                            //解析消息
                            //AddErrMsg()
                            MsgDetail(Rec);
                        }
                    }
                    //發送消息
                    if (cominfo.Q_MsgSend.Count > 0 && cominfo.soc_client.Connected)
                    {
                        //
                        byte[] msg = (byte[])cominfo.Q_MsgSend.Dequeue();
                        cominfo.soc_client.Send(msg);
                        int msg_count = cominfo.Dic_SendMsg.Count;

                        string send_msg = "";
                        for (int i = 0; i < msg.Length; i++)
                        {
                            send_msg += Convert.ToString(msg[i], 16).ToUpper();
                        }
                    }
                    //3次沒有回復認為服務端斷線,自動斷開服務端
                    if (cominfo.heartcount > 3)
                    {
                        cominfo.IsConnected = false;
                        cominfo.soc_client.Disconnect(true);
                        cominfo.heartcount = 0;
                        tm_heart.Stop();
                    }
                });
                }
                catch (Exception ex)
                {

                }
            }

        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值