无服务器端的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# ,