最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

天天快报!C# Socket 通信时,怎样判断 Socket 双方是否断开连接

来源:博客园


(资料图片)

参考内容:

C#socket通信时,怎样判断socket双方是否断开连接

C#之Socket断线和重连

Socket.Poll 方法

Socket.Blocking 属性

最近需要写个网口通信的上位机程序,我负责写客户端,控制多个客户端与多个服务端简历连接进行通讯,关于异常处理一直有问题,写出来做个记录。

建立连接

/// /// 与客户端建立连接:若出错,则开辟一个新线程,在新线程里每隔五秒尝试连接一次,连接成功的话跳出循环,加入到列表中/// private void CreateSocketConnection(){    int countOfServers = dt_ServerInfo.Rows.Count;//dt表中存着服务端的IP地址和端口号    for (int i = 0; i < countOfServers; i++)    {        Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);        IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(dt_ServerInfo.Rows[i]["serverIP"].ToString()),                                                   int.Parse(dt_ServerInfo.Rows[i]["serverPort"].ToString()));        try        {            IAsyncResult result = serverSocket.BeginConnect(serverEndPoint, null, null);            result.AsyncWaitHandle.WaitOne(500);            clientsockets.Add(serverSocket);            socketClients.TryAdd(serverSocket.RemoteEndPoint.ToString(), serverSocket);        }        catch (SocketException) //尝试访问套接字时出错        {            Thread thr_connect = new Thread(() =>                                            {                                                try                                                {                                                    for (int j = 0; j < 10; j++)                                                    {                                                        //serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                                                        serverSocket.Connect(serverEndPoint);                                                        DateTime now = DateTime.Now;                                                        while (now.AddSeconds(5) > DateTime.Now) { }                                                        break;                                                    }                                                    clientsockets.Add(serverSocket);                                                    socketClients.TryAdd(serverSocket.RemoteEndPoint.ToString(), serverSocket);                                                }                                                catch { }                                            });            thr_connect.IsBackground = true;            thr_connect.Start();        }    }}

发送数据

开辟一个线程来专门发送数据:

/*全局变量*/Thread Thr_Send = null;volatile  bool Stopflag = false; //发送停止标志位 - volatile保证不被优化掉......    /*初始化*/Thr_Send = new Thread(new ThreadStart(SendThread));Thr_Send.IsBackground = true;Thr_Send.Start();/*发送线程内容*/private void SendThread()        {            while (true)            {                if (!Stopflag)                {                    try                    {                        foreach (var item in socketClients)                        {                            string serverInfo = item.Key.ToString();                            DataRow[] drs = dt_ServerInfo.Select($"ServerIp = "{serverInfo.Split(":")[0]}" And ServerPort = "{serverInfo.Split(":")[1]}"");                            byte[] sendByte = hexStringToByteArray(drs[0]["Command"].ToString());                            try                            {                                IAsyncResult result = item.Value.BeginSend(sendByte, 0, sendByte.Length, SocketFlags.None, null, null);                                result.AsyncWaitHandle.WaitOne(500);                            }                            catch (SocketException) // 尝试访问套接字时出错                            {                                IPEndPoint tempEndpoint = (IPEndPoint)item.Value.RemoteEndPoint;                                item.Value.Shutdown(SocketShutdown.Both);                                item.Value.Disconnect(true);                                item.Value.Close();                                Socket tempsocket = item.Value;                                socketClients.TryRemove(item.Key, out tempsocket);                                Thread thr_reconnect = new Thread(() =>                                  {                                      try                                      {                                          int j = 0;                                          for (; j < 10; j++)                                          {                                              tempsocket.Connect(tempEndpoint);                                              DateTime now_temp = DateTime.Now;                                              while (now_temp.AddSeconds(5) > DateTime.Now) { }                                              break;                                          }                                          if (j!=10)                                          {                                              socketClients.TryAdd(tempsocket.RemoteEndPoint.ToString(), tempsocket);                                          }                                          Thread.CurrentThread.Abort();                                      }                                      catch { }                                  });                                thr_reconnect.IsBackground = true;                                thr_reconnect.Start();                            }                        }                        DateTime now = DateTime.Now;                        while (now.AddSeconds(1) > DateTime.Now) { }                    }                    catch (Exception ex)                    {                        throw ex;                    }                }            }        }

BeginReceive也是这么写的,就不贴了,我这只处理了客户端程序错误,没有处理上面说的物理问题,我先测测能用不。

心跳检测

这个不会写,不知道对不对

新开了一个线程:

private byte[] GetKeepLiveData(){    uint dummy = 0;    byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];    BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);    BitConverter.GetBytes((uint)3000).CopyTo(inOptionValues, Marshal.SizeOf(dummy)); //keep-alive 间隔    BitConverter.GetBytes((uint)500).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2); //尝试间隔    return inOptionValues;}private void CheckAlive(){    Thread.Sleep(10000);    while (true)    {        try        {            lock (socketClients)            {                foreach (var item in socketClients)                {                    //if (item.Client.Client.Poll(500, System.Net.Sockets.SelectMode.SelectRead) && (item.Client.Client.Available == 0))                    if (item.Value.Poll(500, System.Net.Sockets.SelectMode.SelectRead) && item.Value.Available == 0)                    {                        //MaterialMessageBox.Show("未收到心跳检测回复");                        //心跳检测处理                        item.Value.Shutdown(SocketShutdown.Both);                        item.Value.Disconnect(true);                        item.Value.Close();                        Socket tempsocket = item.Value;                        socketClients.TryRemove(item.Key, out tempsocket);                    }                }            }        }        catch (Exception e)        {            MaterialMessageBox.Show(e.ToString());        }        Thread.Sleep(500);    }}

关键词: 发送数据 断开连接 异常处理