请大侠看看用UdpClient做服务器实现高并发的思路

cekel 2015-05-13 05:47:56
小弟最近项目需要,要做个类似于P2P架构的服务器来登记客户端IP和端口实现打洞。因为客户端数据量大概有三千个,所以要求服务器能撑住三千个并发(因为有心跳机制)。因为从没做过socket开发,加上网上的UDP资料也讲得不够深入,所以小弟将实现思路写出来请各路大侠帮忙看看是否合理。
先讲个小插曲,小弟曾以为异步就是并发,所以用udpclient一下子BeginReceive了三次,以为这样就能一下子处理三个客户端发来的数据。测试时故意让第一次回调先sleep10秒再EndReceive。测试结果,当三个客户端(分别是为A、B、C)同时发数据时,第一次回调所接收的数据竟然被三次的覆盖掉了,即接收到C、B、C。看来同时多个BeginReceive不可取。
好了,有了上面的小插曲,小弟认为UDP无法并行Receive,猜测是系统先收到数据后才会触发回调方法,EndReceive所读取到的数据是由系统冲缓给udpclient的缓冲区的数据,每EndReceive一次UdpClient的缓冲区就会刷新一次,无法保证数据的有序性。
既然无法并行读,那只好顺序读了。网上很多的例子都是这样的
while (true)
{
lock (this)
{
IAsyncResult iar = udpReceive.BeginReceive(new AsyncCallback(ReceiveCallback), udpReceiveState);
receiveDone.WaitOne();
Thread.Sleep(100);
}
}
//回调
private void ReceiveCallback(IAsyncResult iar)
{
UdpState udpReceiveState = iar.AsyncState as UdpState;
Byte[] receiveBytes = udpReceiveState.udpClient.EndReceive(iar, ref udpReceiveState.ipEndPoint);
string receiveString = Encoding.ASCII.GetString(receiveBytes);
//业务处理......
receiveDone.Set();
}


这种代码跟同步有区别么?小弟认为BeginReceive异步其实就是用了线程,如何发挥线程的作用才是重要的,所以小弟把以上代码稍作修改

while (true)
{
lock (this)
{
IAsyncResult iar = udpReceive.BeginReceive(new AsyncCallback(ReceiveCallback), udpReceiveState);
}
Console.ReadLine();
}
//回调
private void ReceiveCallback(IAsyncResult iar)
{
UdpState udpReceiveState = iar.AsyncState as UdpState;
Byte[] receiveBytes = udpReceiveState.udpClient.EndReceive(iar, ref udpReceiveState.ipEndPoint);
//马上进入下一次异步接收
udpclient.BeginReceive(new AsyncCallback(ReceiveCallback), udpReceiveState);
string receiveString = Encoding.ASCII.GetString(receiveBytes);
//业务处理......
}


以上代码的思路就是异步接收,当把数据接收到buffer时,马上告诉udpclient进入下一次异步接收,然后再进行业务逻辑处理。此时是在线程里面发生的,当下一次接收到数据,又是在另一线程里面了,就实现了不同线程处理不同的客户端的数据,所谓的并发了。

大概的思路就是这样,不知道可行否,人家的高并发是怎样的呢?请大侠指点
...全文
414 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
tcmakebest 2015-05-14
  • 打赏
  • 举报
回复
UDP接收的数据来自哪里, 楼主应该判断对方的IP地址的, ref udpReceiveState.ipEndPoint 应该用起来.
cekel 2015-05-13
  • 打赏
  • 举报
回复
嗯,我没有说udpclient有bug,是我前面的测试方法不可取,所以换了思路。麻烦大侠看看我的思路可行不
  • 打赏
  • 举报
回复
“覆盖掉了”那是你的程序有bug。这种程序bug不去解决,而相当轻率地总结成是udpclient有bug,那么你就没有什么办法好好地玩耍编程了。

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧