高效的.Net UDP异步编程实现分析
程序员文章站
2024-03-06 12:53:44
因为要写一个网络程序要用到udp协议,udp这东西比较麻烦,又不像tcp一样提供可靠的连接,发送接收的超时实在不好设计,最后只要用timer来检测有没有想要的数据包-_#,...
因为要写一个网络程序要用到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
{
}
}
代码是不是很简单?功能是不是很强大?
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
{
}
}
代码是不是很简单?功能是不是很强大?
上一篇: Java 匿名内部类详解及实例代码
下一篇: asp.net 组件开发中的内嵌资源引用