原文地址:http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic1887.aspx
在公司一項目的UDP消息服務開發中時不時的會遇到這樣一個問題:在UDP通信過程中,如果客戶端中途斷開,服務器會收到一個SocketException,錯誤ID為10054,描述是“遠程主機強迫關閉了一個現有的連接”,緊接着的事就可怕了,UDP服務終止監聽,所有客戶端都受到了影響。也就是說一個客戶端引起的異常導致了整個系統的崩潰。這個問題可是太嚴重了。
地球人都知道,UDP是無連接的,怎么會出現這個異常呢?百度了一圈,發現有這個問題的現象還不少,可就是沒有一個有效的回復。再GOOGLE一圈,有點眉目了。找到了一個微軟的解釋和一個DOTNET的解決方法:
微軟的解釋:http://support.microsoft.com/kb/263823
DOTNET的處理方法:http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic1887.aspx
不過處理方法似乎對參數的設置不太正確: byte[] optionInValue = { Convert.ToByte(true) }; byte[] optionOutValue;
按照這樣設置還是會拋出該異常。 首先,根據微軟的解釋,optionInValue 傳入的應該是false,而不是true; 其次,根據微軟的解釋,optionOutValue應該是一個DWORD值,不應不賦值,或設為null。
根據以上兩點,將以上兩句改為: byte[] optionInValue = { Convert.ToByte(false) }; byte[] optionOutValue = new byte[4];
經過測試,模擬500個用戶進行登錄、收發消息、注銷、異常退出、再連接,均沒有再拋出該異常。服務表現穩定。
在UDP通信過程中,如果客戶端中途斷開,服務器會收到一個SocketException,錯誤ID為10054,描述是“遠程主機強迫關閉了一個現有的連接”,緊接着的事就可怕了,UDP服務終止監聽,所有客戶端都受到了影響。也就是說一個客戶端引起的異常導致了整個系統的崩潰。
找了好幾天了。終於找到了解決辦法。
在初始化對象后設置屬性如下:
uint IOC_IN = 0x80000000; uint IOC_VENDOR = 0x18000000; uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; ClientSocket.IOControl((int)SIO_UDP_CONNRESET, new byte[] {Convert.ToByte(false)}, null);
Socket.IOControl 方法 (IOControlCode, Byte[], Byte[])
使用 IOControlCode 枚舉指定控制代碼,為 Socket 設置低級操作模式。
參數
- ioControlCode
-
一個 IOControlCode 值,它指定要執行的操作的控制代碼。
- optionInValue
-
Byte 類型的數組,包含操作要求的輸入數據。
- optionOutValue
-
Byte 類型的數組,包含由操作返回的輸出數據。
返回值
optionOutValue 參數中的字節數。
異常
異常類型 條件
試圖訪問套接字時發生錯誤。有關更多信息,請參見備注部分。
Socket 已關閉。
試圖不使用 Blocking 屬性更改阻止模式。
備注
此方法提供對 Socket 類的當前實例所基於的操作系統 Socket 的低級訪問。有關更多信息,請參見 MSDN Library 中的 WSAIoctl 文檔。
本人體會:
再做通信項目中無意中遇到了這個問題,記得上學的時候老師說過UDP是無連接的,但是在項目中遇到了這個遠程主機強制關閉現有連接的錯誤,搞得一頭霧水,什么也不用說,馬上google一下,發現很多朋友都有遇到了這個問題,最后還是看到了原作者的這篇文章后解決了問題,呵呵,再次轉載過來,希望幫助所有遇到這個問題的朋友快速的解決問題。