.Net高效UDP异步编程

来源:互联网 发布:java判断数字长度 编辑:程序博客网 时间:2024/05/20 19:48

     因为要写一个网络程序要用到UDP协议,UDP这东西比较麻烦,又不像TCP一样提供可靠的连接,发送接收的超时实在不好设计,最后只要用Timer来检测有没有想要的数据包-_#,不过这不是这次的重点,重点是怎么建立一种高效的UDP机制来实时接收服务器发送过来的数据包.

     CodeProject上有个例子是开个线程去同步接收,这样倒是可以满足我的程序需求,不过实际中遇到几个问题:

     1.程序开销大,内存狂飙,接一次数据就要重新开一次线程

     2.由于主界面和底层是完全隔离只是通过中间的接口来通讯,导致线程总是不能正常的结束,程序结束后还有一个进程在那里不知道干什么.

     于是翻阅MSDN,查找自己以前写的代码,最后还是决定用异步来接收,MSDN上UDP异步的例子不太好,有点敷衍的意思,用异步很好的解决了以上的问题,高效完成效率,代码如下: 

 

UdpClient qq_client;    //Udp客户端
qq_client = new UdpClient();
IPEndPoint remoteQQEP 
= new IPEndPoint(remotehost, remoteport);
qq_client.Connect(remoteQQEP);


AsyncCallback GetRecvBuffer 
= new AsyncCallback(ReceiveCallback);
qq_client.BeginReceive(GetRecvBuffer, 
null);   

这里用一个GetRecvBuffer的回掉来实现异步

 

        private void ReceiveCallback(IAsyncResult ar)
        
{
            
try
            
{
                
lock (this)
                
{
                    
byte[] recvbytes = qq_client.EndReceive(ar, ref remoteQQEP);
                    
//QQFunction.DebugDump(recvbytes);


                    
if (recvbytes[0!= QQDef.QQ_IM_HEAD && recvbytes[0!= 0x03)
                    
{
                        
//非QQ数据包
                        return;
                    }

                    
switch (Pop16(recvbytes, 3))
                    
{
                        
case QQDef.QQ_REQUEST_TOKEN:
                            DoGetToken(recvbytes);
                            
break;
                        
case QQDef.QQ_REQUEST_LOGIN:
                            DoGetLogin(recvbytes);
                            
break;
                        
case QQDef.QQ_GET_ONLINE_FRIEND:
                            DoGetOnline(recvbytes);
                            
break;
                        
case QQDef.QQ_KEEP_ALIVE:
                            CheckAlive(recvbytes);
                            
break;
                        
case QQDef.QQ_SEND_IM_MSG:
                            
// Do SomeThing
                            break;
                        
case QQDef.QQ_RECV_IM_MSG:
                            DoRecvMsg(recvbytes);
                            
break;
                        
default:
                            QQFunction.DebugDump(
"UnKnow Command");
                            QQFunction.DebugDump(recvbytes);
                            
break;
                    }

                    
                }

                
lock (this)
                
{
                    AsyncCallback GetRecvBuffer 
= new AsyncCallback(ReceiveCallback);
                    qq_client.BeginReceive(GetRecvBuffer, 
null);
                }

            }

            
catch
            
{
            }

        }

 

代码是不是很简单?功能是不是很强大?