首页 > Web开发 > 详细

.net 使用TCP模拟UDP广播通信加强广播通信的稳定性

时间:2019-11-06 10:24:29      阅读:79      评论:0      收藏:0      [点我收藏+]

应用场景:当每一台终端开启程序后发出消息,其他终端必须收到消息然后处理

思路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());
            }

        }
View Code

这边是每隔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());
            }

        }
View Code

 

 

接收广播信号,将其他终端地址添加到本地列表

技术分享图片
  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();
        }
View Code

 

 

开启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
View Code

 

 

发消息时开启多个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();
View Code

 

以上代码是部分代码。仅供参考

 

总结:然并卵

.net 使用TCP模拟UDP广播通信加强广播通信的稳定性

原文:https://www.cnblogs.com/dyr1115/p/11803467.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!