2011-12-05 9 views
3

的基本代碼序列我對有趣的是(僞)上的ICMP Responsing在選擇

sendto(some host); // host may be unreachable for now which is normal 
... 
if(select(readfs, timeout)) // there are some data to read 
    recvfrom(); 

由於Win2000的,ICMP報文,發送UDP數據報給端口不可達後發回,觸發選擇,後recvfrom使用WSAECONNRESET失敗。這種行爲對我來說是不可取的,因爲我希望在這種情況下選擇超時完成(沒有要讀取的數據)。在Windows上,這可以通過WSAIoctl SIO_UDP_CONNRESET(http://support.microsoft.com/kb/263823)解決。

我的問題是:

  1. 是SIO_UDP_CONNRESET在這種情況下,最好的方法是什麼?
  2. 是否有一些其他方法忽略ICMP的「選擇」或篩選recvfrom(也許,忽略Windows上的WSAECONNRESET錯誤對待它像超時,可以在其他情況下觸發此錯誤)?
  3. Linux和Unix(Solaris,OpenBSD)有類似的問題嗎?
+0

您只會使用連接一次嗎?如果不是,如果您從未收到錯誤,告訴您連接不再處於活動狀態並且應該關閉,您將如何知道何時關閉連接? –

+0

我想繼續發送數據報,直到遠程主機(實際上它是一些嵌入式系統)啓動或用戶終止此操作。 – Yury

+0

從Linux移植應用程序時出現此錯誤。在我的情況下,它是一個非阻塞的UDP數據報廣播,我不想關閉連接,如果客戶端死了我開始在服務器上的recv上收到WSAECONNRESET錯誤!這似乎錯誤不明確。由SIO_UDP_CONNRESET修復,但在我看來,就像Winsock中的一個錯誤。 – dashesy

回答

2

select()readfds集真的只是報道稱,插座read()不會阻止 - 它並不保證有關是否有可讀取實際數據什麼。

我不知道你在想什麼專門與兩秒的超時來完成,而不是隻是在睡覺永遠 - 也不知道爲什麼你不能只是增加一個if塊檢查WSAECONNRESETrecvfrom() - 但如果它不能很好地處理這種情況,就會覺得你的設計過於複雜。

許多Linux系統上的select_tut(2)聯機幫助頁有正確使用select()的一些準則。以下是幾條適用於您的情況的規則:

1. You should always try to use select() without a timeout. 
     Your program should have nothing to do if there is no 
     data available. Code that depends on timeouts is not 
     usually portable and is difficult to debug. 

    ... 

    3. No file descriptor must be added to any set if you do not 
     intend to check its result after the select() call, and 
     respond appropriately. See next rule. 

    4. After select() returns, all file descriptors in all sets 
     should be checked to see if they are ready. 
+0

我想支持溫和的用戶中斷(實際上這個模塊只是該軟件的一小部分),所以如果有數據,我會週期性地調用帶有超時和recvfrom的select。我想讀取數據,如果可能的話,儘可能少的超時,所以我不能使用睡眠;另一方面,如果沒有數據,則不應該有任何開銷。非常感謝您的回覆,我會研究。 – Yury

+0

如果用戶「中斷」通過套接字傳送,您可以將其添加到您的「選擇」調用... – sarnold

+0

不,我的意思是從用戶界面中斷(=終止)。此代碼在特殊線程中運行,並且此線程由另一個模塊控制。當然,可以硬線程結束,但我需要小心和控制退出(對於互斥體等)。 – Yury