当前位置:编程学习 > C#/ASP.NET >>

无服务器端的UDP群聊功能剖析

 

我以前在使用飞鸽传书功能的时候,发现只要打开这个软件,局域网中的用户就会瞬间加载到我的用户列表中,同时在局域网中的用户的列表中马上也会加载我自己的用户信息。而且,飞鸽传书软件没有依靠服务器端的中转,也就是说,完全是客户端的功能。

那么这种机制到底是如何实现的呢?下面来一步一步的剖析。

首先,我上线,局域网中的用户能够加载到我的用户列表中,那么我上线的时候,肯定是局域网中的用户都到了我的上线消息,然后给我回复了一条包含他们IP地址的信息,那样,我就可以逐个来添加他们到列表中了。

其次,我上线后,他们的列表中能够添加我的用户信息,那么这个肯定是我上线的时候,侦测到了局域网中的用户,然后对每个用户发送了一个包含我的IP地址的报文。需要在这里注意的是,发送报文的时候,一定要注意广播风暴。(记得当时做测试的时候,由于广播风暴,将整整6个人的网络全部占用完毕,连网络都上不成。)

最后就是下线,当局域网有用户下线的时候,下线用户肯定是发送了一个包含自己IP地址的下线通知,然后我们的软件收到之后,将他从列表中删除。

当然,现在我们所有的想象只是猜测,现在来具体化设计一下:

上线,我们可以封装类似0x01 ip地址  信息格式内容发送给局域网用户,用户通过拆解发送内容的标志符号0x01来确定发送的数据类型。

聊天,我们可以封装类似0x02 ip地址  聊天内容 信息格式的内容发送给用户,用户通过拆解0x02标志来确定这条消息是聊天内容。

下线也是类似的,也是通过拆解来完成,那么如何实现无服务器端的呢?

其实这个问题很好回答,就是开一个监听线程,让它在那儿一直轮训套接字端口的接收信息,如果接收到数据,通过拆解包头,再进行对应的处理:

 /// <summary>

        /// 监听事件

        /// </summary>

        private void listenRemote()

        {

            IPEndPoint ipEnd = new IPEndPoint(broadIPAddress,lanPort);

            try

            {

                while (isRun)

                {

                    try

                    {

                        byte[] recInfo = listenClient.Receive(ref ipEnd);  //接受内容,存储到byte数组中

                           DealWithAcceptedInfo(recInfo); //处理接收到的数据

                    }

                    catch (Exception ex)

                    {

                        MessageBox.Show(ex.Message);

                    }

                }

                listenClient.Close();

                isRun = false;

            }

            catch (SocketException se) { }  //捕捉试图访问套接字时发生错误。

              catch (ObjectDisposedException oe) { } //捕捉Socket 已关闭

              catch (InvalidOperationException pe) { } //捕捉试图不使用Blocking 属性更改阻止模式。

        }

 

        /// <summary>

        /// 方法:处理接到的数据

        /// </summary>

        private void DealWithAcceptedInfo(byte[] recData)

        {

            string recStr = Encoding.Default.GetString(recData);

            string[] _recStr = recStr.Split('|');

            switch (_recStr[0])

            {

                case "0x00":  //用户上线

                    SendInfoOnline(_recStr[1]);

                    if (lstUsers.FindString(_recStr[1] + "---" + _recStr[2]) <= 0)  //如果用户不存在

                       {

                        addListBox(_recStr[1] + "---" + _recStr[2]);

                        AddLogIntoListBox("用户【" + _recStr[1] + "】已经上线!");

                    }

                    break;

                case "0x01":  //用户聊天

                    AddTextBox(_recStr[1] + "    " + DateTime.Now + "\r\n", 1, 2);  //这是接收到了别人发来的信息

                    SendContentFromBox(_recStr[3].ToString());

                    break;

                case "0x02":  //抖动屏幕

                    flickerWin();

                    break;

          

补充:软件开发 , C# ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,