问题描述
小弟最近项目需要,要做个类似于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){IAsyncResultiar=udpReceive.BeginReceive(newAsyncCallback(ReceiveCallback),udpReceiveState);receiveDone.WaitOne();Thread.Sleep(100);}}//回调privatevoidReceiveCallback(IAsyncResultiar){UdpStateudpReceiveState=iar.AsyncStateasUdpState;Byte[]receiveBytes=udpReceiveState.udpClient.EndReceive(iar,refudpReceiveState.ipEndPoint);stringreceiveString=Encoding.ASCII.GetString(receiveBytes);//业务处理......receiveDone.Set();}
这种代码跟同步有区别么?小弟认为BeginReceive异步其实就是用了线程,如何发挥线程的作用才是重要的,所以小弟把以上代码稍作修改while(true){lock(this){IAsyncResultiar=udpReceive.BeginReceive(newAsyncCallback(ReceiveCallback),udpReceiveState);}Console.ReadLine();}//回调privatevoidReceiveCallback(IAsyncResultiar){UdpStateudpReceiveState=iar.AsyncStateasUdpState;Byte[]receiveBytes=udpReceiveState.udpClient.EndReceive(iar,refudpReceiveState.ipEndPoint);//马上进入下一次异步接收udpclient.BeginReceive(newAsyncCallback(ReceiveCallback),udpReceiveState);stringreceiveString=Encoding.ASCII.GetString(receiveBytes);//业务处理......}
以上代码的思路就是异步接收,当把数据接收到buffer时,马上告诉udpclient进入下一次异步接收,然后再进行业务逻辑处理。此时是在线程里面发生的,当下一次接收到数据,又是在另一线程里面了,就实现了不同线程处理不同的客户端的数据,所谓的并发了。大概的思路就是这样,不知道可行否,人家的高并发是怎样的呢?请大侠指点
解决方案
解决方案二:
“覆盖掉了”那是你的程序有bug。这种程序bug不去解决,而相当轻率地总结成是udpclient有bug,那么你就没有什么办法好好地玩耍编程了。
解决方案三:
嗯,我没有说udpclient有bug,是我前面的测试方法不可取,所以换了思路。麻烦大侠看看我的思路可行不
解决方案四:
UDP接收的数据来自哪里,楼主应该判断对方的IP地址的,refudpReceiveState.ipEndPoint应该用起来.