生活随笔
收集整理的這篇文章主要介紹了
C#UDP通讯UdpClient
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
目錄(?)[+]
遇到如下兩個(gè)問題 遠(yuǎn)程主機(jī)強(qiáng)迫關(guān)閉了一個(gè)現(xiàn)有的連接的錯(cuò)誤
[html] view plaincopy print?
class?UdpClientClass??{??????///?<summary>??????///?構(gòu)建客戶端??????///?</summary>??????///?<param?name="servierIpAddress">服務(wù)器iP地址或者域名</param>??????///?<param?name="sevierPort">服務(wù)器監(jiān)聽端口</param>??????///?<param?name="locadPort">本地監(jiān)聽端口</param>??????///?<param?name="timeOut">超時(shí)等待時(shí)間</param>??????public?UdpClientClass(string?servierIpAddress,?int?sevierPort,?int?locadPort,?int?timeOut)??????{??????????if?(FpHelper.CheckIpAddress(ref?servierIpAddress)?==?true)??????????{??????????????try??????????????{??????????????????ServerIPE?=?new?IPEndPoint(IPAddress.Parse(servierIpAddress),?sevierPort);??????????????????UdpListenClient?=?new?UdpClient(locadPort);//固定通信端口??????????????????UdpListenClient.Client.ReceiveTimeout?=?3000;??????????????????const?long?IOC_IN?=?0x80000000;??????????????????const?long?IOC_VENDOR?=?0x18000000;??????????????????const?long?SIO_UDP_CONNRESET?=?IOC_IN?|?IOC_VENDOR?|?12;????????????????????byte[]?optionInValue?=?{?Convert.ToByte(false)?};??????????????????byte[]?optionOutValue?=?new?byte[4];????????????????????UdpListenClient.Client.IOControl((IOControlCode)SIO_UDP_CONNRESET,?optionInValue,?optionOutValue);?????????????????????????????????}??????????????catch?(System.Exception?ex)??????????????{??????????????????MessageBox.Show("綁定端口失敗"?+?ex.Message.ToString());??????????????}????????????}??????}????????///?<summary>??????///?UDP發(fā)送類,綁定了一個(gè)固定的端口??????///?</summary>??????private?static?UdpClient?UdpListenClient;????????public?event?EventHandler?MessageChanged;????????///?<summary>??????///?接收到服務(wù)器消息改變后觸發(fā)的事件??????///?</summary>??????///?<param?name="user"></param>??????public?void?OnMessageChanged(UdpClientClass?fp)??????{??????????if?(MessageChanged?!=?null)??????????{??????????????MessageChanged(fp,?null);??????????}??????}????????///?<summary>??????///?服務(wù)器端的IP與端口??????///?</summary>??????private?IPEndPoint?ServerIPE?=?null;????????bool?IsReceiving?=?false;????????public?void?Send(byte[]?data,?int?len)??????{????????int?len1?=??UdpListenClient.Send(data,?len,?ServerIPE);??????????if?(!IsReceiving)??????????????StartAndLsn();??????}????????private?Thread?ClientRecThread;????????private?void?StartAndLsn()??????{??????????IsReceiving?=?true;??????????ClientRecThread?=?new?Thread(new?ThreadStart(RecF));//啟動(dòng)新線程做接收??????????ClientRecThread.IsBackground?=?true;??????????ClientRecThread.Start();????????}//啟動(dòng)并且?監(jiān)聽?服務(wù)器發(fā)來的數(shù)據(jù)??????????private?void?RecF()//接收數(shù)據(jù)做服務(wù)??????{??????????byte[]?btRec?=?null;??????????while?(IsReceiving)??????????{??????????????IPEndPoint?remoteIPE?=?new?IPEndPoint(IPAddress.Any,?0);??????????????btRec?=?UdpListenClient.Receive(ref?remoteIPE);//UDP接收數(shù)據(jù)??????????????if?(btRec.Length?>?0?&&?remoteIPE.Address?==?ServerIPE.Address)//只處理特定的服務(wù)端的數(shù)據(jù)??????????????{??????????????????System.Windows.Forms.MessageBox.Show("res");??????????????}??????????????else??????????????{??????????????}????????????}??????}//循環(huán)接收數(shù)據(jù)??}?? class UdpClientClass{/// <summary>/// 構(gòu)建客戶端/// </summary>/// <param name="servierIpAddress">服務(wù)器iP地址或者域名</param>/// <param name="sevierPort">服務(wù)器監(jiān)聽端口</param>/// <param name="locadPort">本地監(jiān)聽端口</param>/// <param name="timeOut">超時(shí)等待時(shí)間</param>public UdpClientClass(string servierIpAddress, int sevierPort, int locadPort, int timeOut){if (FpHelper.CheckIpAddress(ref servierIpAddress) == true){try{ServerIPE = new IPEndPoint(IPAddress.Parse(servierIpAddress), sevierPort);UdpListenClient = new UdpClient(locadPort);//固定通信端口UdpListenClient.Client.ReceiveTimeout = 3000;const long IOC_IN = 0x80000000;const long IOC_VENDOR = 0x18000000;const long SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;byte[] optionInValue = { Convert.ToByte(false) };byte[] optionOutValue = new byte[4];UdpListenClient.Client.IOControl((IOControlCode)SIO_UDP_CONNRESET, optionInValue, optionOutValue);}catch (System.Exception ex){MessageBox.Show("綁定端口失敗" + ex.Message.ToString());}}}/// <summary>/// UDP發(fā)送類,綁定了一個(gè)固定的端口/// </summary>private static UdpClient UdpListenClient;public event EventHandler MessageChanged;/// <summary>/// 接收到服務(wù)器消息改變后觸發(fā)的事件/// </summary>/// <param name="user"></param>public void OnMessageChanged(UdpClientClass fp){if (MessageChanged != null){MessageChanged(fp, null);}}/// <summary>/// 服務(wù)器端的IP與端口/// </summary>private IPEndPoint ServerIPE = null;bool IsReceiving = false;public void Send(byte[] data, int len){int len1 = UdpListenClient.Send(data, len, ServerIPE);if (!IsReceiving)StartAndLsn();}private Thread ClientRecThread;private void StartAndLsn(){IsReceiving = true;ClientRecThread = new Thread(new ThreadStart(RecF));//啟動(dòng)新線程做接收ClientRecThread.IsBackground = true;ClientRecThread.Start();}//啟動(dòng)并且 監(jiān)聽 服務(wù)器發(fā)來的數(shù)據(jù)private void RecF()//接收數(shù)據(jù)做服務(wù){(diào)byte[] btRec = null;while (IsReceiving){IPEndPoint remoteIPE = new IPEndPoint(IPAddress.Any, 0);btRec = UdpListenClient.Receive(ref remoteIPE);//UDP接收數(shù)據(jù)if (btRec.Length > 0 && remoteIPE.Address == ServerIPE.Address)//只處理特定的服務(wù)端的數(shù)據(jù){System.Windows.Forms.MessageBox.Show("res");}else{}}}//循環(huán)接收數(shù)據(jù)}
遇到如下兩個(gè)問題
[html] view plaincopy print?
1.UdpListenClient.Receive接受數(shù)據(jù)位阻塞模式,一直等待對方的返回,網(wǎng)上詢問這個(gè)問題的很多,解答的卻很多答非所問,仔細(xì)查看了UdpClient?類發(fā)現(xiàn)里面有一個(gè)Socket熟悉,?? 1.UdpListenClient.Receive接受數(shù)據(jù)位阻塞模式,一直等待對方的返回,網(wǎng)上詢問這個(gè)問題的很多,解答的卻很多答非所問,仔細(xì)查看了UdpClient 類發(fā)現(xiàn)里面有一個(gè)Socket熟悉,
[html] view plaincopy print?
關(guān)于通訊的底層問題都通過該熟悉來設(shè)置,該熟悉又設(shè)置發(fā)送或者接受超時(shí)的設(shè)置,如?? 關(guān)于通訊的底層問題都通過該熟悉來設(shè)置,該熟悉又設(shè)置發(fā)送或者接受超時(shí)的設(shè)置,如
[html] view plaincopy print?
UdpListenClient.Client.ReceiveTimeout?=?3000;//設(shè)置超時(shí)接收返回?? UdpListenClient.Client.ReceiveTimeout = 3000;//設(shè)置超時(shí)接收返回
[html] view plaincopy print?
2.udp通訊發(fā)現(xiàn)有時(shí)會(huì)產(chǎn)生<h2><a?name="t1"></a><a?class="singleposttitle"?id="ctl01_TitleUrl"?href="http://www.cnblogs.com/zhuangxuqiang/archive/2009/04/17/1437926.html">遠(yuǎn)程主機(jī)強(qiáng)迫關(guān)閉了一個(gè)現(xiàn)有的連接</a>的錯(cuò)誤</h2><p>網(wǎng)上查找了很多,終于看到一篇</p><div?id="cnblogs_post_body"><p>在公司一項(xiàng)目的UDP消息服務(wù)開發(fā)中時(shí)不時(shí)的會(huì)遇到這樣一個(gè)問題:在UDP通信過程中,如果客戶端中途斷開,服務(wù)器會(huì)收到一個(gè)SocketException,錯(cuò)誤ID為10054,描述是“遠(yuǎn)程主機(jī)強(qiáng)迫關(guān)閉了一個(gè)現(xiàn)有的連接”,緊接著的事就可怕了,UDP服務(wù)終止監(jiān)聽,所有客戶端都受到了影響。也就是說一個(gè)客戶端引起的異常導(dǎo)致了整個(gè)系統(tǒng)的崩潰。這個(gè)問題可是太嚴(yán)重了。</p><p>地球人都知道,UDP是無連接的,怎么會(huì)出現(xiàn)這個(gè)異常呢?百度了一圈,發(fā)現(xiàn)有這個(gè)問題的現(xiàn)象還不少,可就是沒有一個(gè)有效的回復(fù)。再GOOGLE一圈,有點(diǎn)眉目了。找到了一個(gè)微軟的解釋和一個(gè)DOTNET的解決方法:</p><p>微軟的解釋:<a?href="http://support.microsoft.com/kb/263823"><span?style="color:#0000ff;">http://support.microsoft.com/kb/263823</span></a></p><p>DOTNET的處理方法:<a?href="http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic1887.aspx"><span?style="color:#0000ff;">http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic1887.aspx</span></a></p><p>不過處理方法似乎對參數(shù)的設(shè)置不太正確:??byte[]?optionInValue?=?{?Convert.ToByte(true)?};??byte[]?optionOutValue;</p><p>按照這樣設(shè)置還是會(huì)拋出該異常。??首先,根據(jù)微軟的解釋,optionInValue?傳入的應(yīng)該是false,而不是true;??其次,根據(jù)微軟的解釋,optionOutValue應(yīng)該是一個(gè)DWORD值,不應(yīng)不賦值,或設(shè)為null。</p><p>根據(jù)以上兩點(diǎn),將以上兩句改為:??byte[]?optionInValue?=?{?Convert.ToByte(false)?};??byte[]?optionOutValue?=?new?byte[4];</p><p>經(jīng)過<a?title="軟件測試知識庫"?class="replace_word"?style="color:#df3434;?font-weight:bold;"?href="http://lib.csdn.net/base/softwaretest"?target="_blank">測試</a>,模擬500個(gè)用戶進(jìn)行登錄、收發(fā)消息、注銷、異常退出、再連接,均沒有再拋出該異常。服務(wù)表現(xiàn)穩(wěn)定。</p></div><p>?</p>?? 2.udp通訊發(fā)現(xiàn)有時(shí)會(huì)產(chǎn)生
遠(yuǎn)程主機(jī)強(qiáng)迫關(guān)閉了一個(gè)現(xiàn)有的連接的錯(cuò)誤
網(wǎng)上查找了很多,終于看到一篇
在公司一項(xiàng)目的UDP消息服務(wù)開發(fā)中時(shí)不時(shí)的會(huì)遇到這樣一個(gè)問題:在UDP通信過程中,如果客戶端中途斷開,服務(wù)器會(huì)收到一個(gè)SocketException,錯(cuò)誤ID為10054,描述是“遠(yuǎn)程主機(jī)強(qiáng)迫關(guān)閉了一個(gè)現(xiàn)有的連接”,緊接著的事就可怕了,UDP服務(wù)終止監(jiān)聽,所有客戶端都受到了影響。也就是說一個(gè)客戶端引起的異常導(dǎo)致了整個(gè)系統(tǒng)的崩潰。這個(gè)問題可是太嚴(yán)重了。
地球人都知道,UDP是無連接的,怎么會(huì)出現(xiàn)這個(gè)異常呢?百度了一圈,發(fā)現(xiàn)有這個(gè)問題的現(xiàn)象還不少,可就是沒有一個(gè)有效的回復(fù)。再GOOGLE一圈,有點(diǎn)眉目了。找到了一個(gè)微軟的解釋和一個(gè)DOTNET的解決方法:
微軟的解釋:http://support.microsoft.com/kb/263823
DOTNET的處理方法:http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic1887.aspx
不過處理方法似乎對參數(shù)的設(shè)置不太正確:
byte[] optionInValue = { Convert.ToByte(true) };
byte[] optionOutValue;
按照這樣設(shè)置還是會(huì)拋出該異常。
首先,根據(jù)微軟的解釋,optionInValue 傳入的應(yīng)該是false,而不是true;
其次,根據(jù)微軟的解釋,optionOutValue應(yīng)該是一個(gè)DWORD值,不應(yīng)不賦值,或設(shè)為null。
根據(jù)以上兩點(diǎn),將以上兩句改為:
byte[] optionInValue = { Convert.ToByte(false) };
byte[] optionOutValue = new byte[4];
經(jīng)過測試,模擬500個(gè)用戶進(jìn)行登錄、收發(fā)消息、注銷、異常退出、再連接,均沒有再拋出該異常。服務(wù)表現(xiàn)穩(wěn)定。
?
總結(jié)
以上是生活随笔為你收集整理的C#UDP通讯UdpClient的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。