高效的.Net UDP異步編程實現(xiàn)分析
更新時間:2012年11月30日 11:36:54 作者:
重點是怎么建立一種高效的UDP機(jī)制來實時接收服務(wù)器發(fā)送過來的數(shù)據(jù)包.本文將介紹.Net UDP異步編程如何實現(xiàn)解決方案,有需求的朋友可以參考下
因為要寫一個網(wǎng)絡(luò)程序要用到UDP協(xié)議,UDP這東西比較麻煩,又不像TCP一樣提供可靠的連接,發(fā)送接收的超時實在不好設(shè)計,最后只要用Timer來檢測有沒有想要的數(shù)據(jù)包-_#,不過這不是這次的重點,重點是怎么建立一種高效的UDP機(jī)制來實時接收服務(wù)器發(fā)送過來的數(shù)據(jù)包.
CodeProject上有個例子是開個線程去同步接收,這樣倒是可以滿足我的程序需求,不過實際中遇到幾個問題:
1.程序開銷大,內(nèi)存狂飆,接一次數(shù)據(jù)就要重新開一次線程
2.由于主界面和底層是完全隔離只是通過中間的接口來通訊,導(dǎo)致線程總是不能正常的結(jié)束,程序結(jié)束后還有一個進(jìn)程在那里不知道干什么.
于是翻閱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的回掉來實現(xiàn)異步
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數(shù)據(jù)包
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
{
}
}
代碼是不是很簡單?功能是不是很強(qiáng)大?
CodeProject上有個例子是開個線程去同步接收,這樣倒是可以滿足我的程序需求,不過實際中遇到幾個問題:
1.程序開銷大,內(nèi)存狂飆,接一次數(shù)據(jù)就要重新開一次線程
2.由于主界面和底層是完全隔離只是通過中間的接口來通訊,導(dǎo)致線程總是不能正常的結(jié)束,程序結(jié)束后還有一個進(jìn)程在那里不知道干什么.
于是翻閱MSDN,查找自己以前寫的代碼,最后還是決定用異步來接收,MSDN上UDP異步的例子不太好,有點敷衍的意思,用異步很好的解決了以上的問題,高效完成效率,代碼如下:
復(fù)制代碼 代碼如下:
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的回掉來實現(xiàn)異步
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數(shù)據(jù)包
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
{
}
}
代碼是不是很簡單?功能是不是很強(qiáng)大?
相關(guān)文章
基于.net core微服務(wù)的另一種實現(xiàn)方法
這篇文章主要給大家介紹了基于.net core微服務(wù)的另一種實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
ASP.NET MVC中Controller控制器向View視圖傳值的幾種方式
這篇文章介紹了ASP.NET MVC中Controller控制器向View視圖傳值的幾種方式,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03
使用pdfbox實現(xiàn)pdf文本提取和合并功能示例
這篇文章主要介紹了使用pdfbox實現(xiàn)pdf文本提取和合并功能示例,大家參考使用吧2014-01-01
ASP.NET2.0中數(shù)據(jù)源控件之異步數(shù)據(jù)訪問
ASP.NET2.0中數(shù)據(jù)源控件之異步數(shù)據(jù)訪問...2006-09-09

