应用场景:当每一台终端开启程序后发出消息,其他终端必须收到消息然后处理
思路1:使用UDP广播。 缺点:UDP广播信号不稳定,无法确定每一台机器能接收到信号
思路2:将一台主机作为服务器,使用TCP协议用此服务器转发消息 缺点:需要另外开发服务端,且其他端必须配置IP,灵活性差。
本文讲述的是第三个思路
思路3:开启程序后先设法发现其他终端,每个终端开启一个TCP服务socket,需要发广播的机器开启多个TCP客户端连接其他终端的TCP服务端稳定通信,至于如何使所有终端能相互发现 本文使用的是用UDP广播信号暴露自己,另外还可使用局域网遍历端口等方式。
代码:
发广播暴露自己:
Thread BroadcastTh; /// <summary> /// 发起广播使其他终端能检测到 /// </summary> public void StartBroadCast() { try { if (BroadcastTh != null) { BroadcastTh.Abort(); } BroadcastTh = new Thread(() => { int i = 0; while (i < 200) { i++; Thread.Sleep(500); SendBroadcast("ConnectMe", 9991); } }); BroadcastTh.IsBackground = true; BroadcastTh.Start(); } catch (Exception ex) { SimpleLog.WriteLog(ex.ToString()); } }
这边是每隔500毫秒连续发200次,也可以无限发送广播,本人有强迫症不喜欢 while(true),况且如果开启的机器太多机器发送的广播量太多,相互监听的就越多,影响通信流量。
public void SendBroadcast(string msg, int port) { try { Socket recieveSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Broadcast, port); byte[] data = Encoding.UTF8.GetBytes(msg); recieveSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); recieveSock.SendTo(data, iep); } catch (Exception ex) { SimpleLog.WriteLog(ex.ToString()); } }
接收广播信号,将其他终端地址添加到本地列表
Socket BroadcastRecievesocket; /// <summary> /// 监听广播信号 /// </summary> public void ReceiveBroadcast() { Thread receiveThread = new Thread(() => { try { BroadcastRecievesocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9991); EndPoint ep = (EndPoint)iep; BroadcastRecievesocket.Bind(iep); while (true) { try { byte[] buffer = new byte[1024]; BroadcastRecievesocket.ReceiveFrom(buffer, ref ep); string msg = Encoding.UTF8.GetString(buffer); string endaddress = ep.ToString().Split(‘:‘)[0]; if (msg.Replace("\0","") == "ConnectMe") { if (!SocketList.ContainsKey(endaddress) && endaddress != localhost) { StartBroadCast(); SocketList.Add(endaddress, null); } } else if (msg.Replace("\0", "") == "Offline") { if (SocketList.ContainsKey(endaddress)) SocketList.Remove(endaddress); } // MessageBox.Show(time); } catch (Exception ex) { SimpleLog.WriteLog(ex.ToString()); } } } catch (Exception) { BroadcastRecievesocket.Dispose(); ReceiveBroadcast(); } }) { IsBackground = true }; receiveThread.Start(); }
开启tcp服务端
#region TCP服务端 Socket socketWatch; /// <summary> /// 启动TCP服务端socket /// </summary> private void StartTCPServer() { try { socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //点击开始监听时 在服务端创建一个负责监听IP和端口号的Socket IPAddress ip = IPAddress.Any; //创建对象端口 IPEndPoint point = new IPEndPoint(ip, 9992); socketWatch.Bind(point);//绑定端口号 socketWatch.Listen(10);//设置监听 Thread thread = new Thread(Listen); thread.IsBackground = true; thread.Start(socketWatch); } catch (Exception ex) { SimpleLog.WriteLog(ex.ToString()); } } private void Listen(object o) { try { Socket socketWatch = o as Socket; while (true) { Socket socketSend = socketWatch.Accept();//等待接收客户端连接 Thread r_thread = new Thread(Received); r_thread.IsBackground = true; r_thread.Start(socketSend); } } catch (Exception ex) { SimpleLog.WriteLog(ex.ToString()); } } /// <summary> /// 服务器端不停的接收客户端发来的消息 /// </summary> /// <param name="o"></param> void Received(object o) { try { Socket socketSend = o as Socket; while (true) { //客户端连接服务器成功后,服务器接收客户端发送的消息 byte[] buffer = new byte[1024]; //实际接收到的有效字节数 int len = socketSend.Receive(buffer); if (len == 0) { break; } string str = Encoding.UTF8.GetString(buffer, 0, len); HandleTime(str); } } catch (Exception ex) { SimpleLog.WriteLog(ex.ToString()); } } #endregion
发消息时开启多个TCP客户端连接列表中IP地址对应的服务端
Thread broadcast = new Thread(() => { string[] keyStr = SocketList.Keys.ToArray(); for (int i = keyStr.Length - 1; i >= 0; i--) { try { Socket socketitem; if (SocketList[keyStr[i]] != null) { socketitem = SocketList[keyStr[i]]; } else { socketitem = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ; IPAddress ip = IPAddress.Parse(keyStr[i]); IPEndPoint point = new IPEndPoint(ip, 9992); socketitem.Connect(point); } DateTime dateTime = DateTime.Now; string minisec = (Convert.ToDecimal(dateTime.Millisecond) / 1000).ToString("0.0000"); socketitem.Send(Encoding.UTF8.GetBytes(dateTime.ToLongTimeString() + minisec.Substring(1, minisec.Length - 1))); } catch (Exception ex) { SimpleLog.WriteLog(ex.ToString()); SocketList.Remove(keyStr[i]); } } }); broadcast.IsBackground = true; broadcast.Start();
以上代码是部分代码。仅供参考
总结:然并卵
原文:https://www.cnblogs.com/dyr1115/p/11803467.html