2011-04-28 63 views
2

我在Linux下運行的C++程序中有一個UDP文件描述符。我呼叫connect()將它連接到一個遠程地址,然後從該套接字讀取和寫入。什麼時候連接的UDP套接字會被OS關閉?

根據UNIX網絡編程,「異步錯誤返回到連接的UDP套接字的進程」。我猜測這些異步錯誤會導致操作系統關閉UDP套接字,但這本書並不清楚。也不清楚哪種類型的異步錯誤是可能的,儘管建議如果遠程機器上的端口未打開,套接字將被關閉。

所以我的問題是:在什麼情況下Linux會關閉UDP文件描述符?

  • 壞端口號?
  • 錯誤的IP地址?
  • 其他?
+2

UDP套接字無法連接,請檢查http://en.wikipedia.org/wiki/Berkeley_sockets#Client_2 – bobah 2011-04-28 19:13:04

+1

不,他們可以 - 閱讀connect()的手冊頁:「如果s是SOCK_DGRAM類型,它會永久性地指定發送消息的對等體。「正如我在問題中提到的那樣,_UNIX網絡編程_指出將爲所連接的UDP套接字返回異步錯誤_will_。 – 2011-04-30 04:07:43

回答

4

UDP套接字上的connect()只記錄您傳入的端口號和IP地址,因此它只接受來自該IP /端口的數據包,並且您可以使用套接字fd發送/寫入數據而不指定每個發送/寫入呼叫的遠程地址。關於這一點,異步錯誤意味着如果你發送()一些東西,並且發送調用會導致稍後發生錯誤(例如,當TCP/IP堆棧實際發送數據包或稍後返回一個ICMP數據包時),一個後續發送將返回該錯誤。這種異步錯誤僅在「連接的」UDP套接字上返回。 (linux udp(7)聯機幫助頁提示無論套接字是否連接都會返回錯誤,但測試顯示,至少當發送的UDP數據包生成ICMP錯誤時,情況並非如此。如果你在該套接字上使用recv()而不是隨後的send()調用產生錯誤,可能會返回send()錯誤)

雖然套接字未關閉,但您必須自己關閉它通過調用close()或退出程序。例如如果您連接()您的UDP套接字,併發送到無人接聽端口,則通常會返回ICMP數據包,並且隨後的send()調用將失敗,並將errno設置爲ECONNREFUSED。但是,您可以繼續在該套接字上發送,但不會被操作系統關閉,並且如果有人開始在端口上收聽數據包,則數據包將通過。

+1

因此它總是處於「可恢復」狀態?只要另一端恢復,套接字將重新開始工作?好的,那就是我想知道的。謝謝。 – 2011-04-30 04:10:10

5

UDP套接字是無連接的,所以沒有真正的重視他們「開放」狀態感 - 這是不同於TCP套接字,其中一個插槽可以是任何數量的連接狀態,如通過數據包起來的交易所決定到一個給定的點。

UDP套接字可以被打開和關閉的唯一意義在於它們是具有一些內部狀態和文件描述符的系統級對象。如果發生錯誤,套接字永遠不會自動關閉,並且將無限期地保持打開狀態,除非它們的擁有進程終止或調用其上的close

若要解決您的其他問題,如果目標主機上的目標端口未打開,則UDP數據包的發送者永遠不會知道。** UDP不提供接收方應答的手段。數據包被路由,如果它到達主機,檢查是否正確,並且成功接收或丟棄。當寫入UDP套接字時,send可能返回錯誤代碼的原因很多,但它們都不涉及接收主機的狀態。**我建議查閱sendtomanpage查找可能的故障模式。另一方面,在TCP套接字嘗試連接到未打開的端口的情況下,發送方永遠不會收到其初始連接請求的確認,並且最終connect將失敗。此時,發送端會停止通過套接字發送數據(因爲這隻會產生更多錯誤),但即使在這種情況下,套接字文件描述符也不會自動關閉。

**請參閱@Zuljin在回覆中的回覆。

+1

「如果目標主機上的目標端口未打開,UDP數據包的發送者永遠不會知道」 - 我不能同意這一點。某些操作系統(我不確定是否全部)在目標端口未打開時返回ICMP目標不可達消息。發件人可以檢測到這種情況。我認爲在Windows發送者recvfrom函數將失敗,錯誤WSAECONNRESET。我不確定在其他操作系統上如何檢測到這種情況。 – Zuljin 2011-04-28 19:48:51

+0

@Zuljin,謝謝你的信息。我沒有意識到這一點!我認爲最終答案中更相關的部分仍然存在。即UDP「連接」不存在,並且UDP套接字永遠不會由失敗的I/O過程自動關閉。 – 2011-04-28 20:24:18

+0

我也沒有意識到這一點,直到我的應用程序開始崩潰時服務器關閉UDP端口:)。這在socket編程教程中很難找到,在大多數情況下,處理這種情況並不是必需的。正如我所提到的,我甚至不確定是否所有流行的操作系統默認發送此ICMP軟件包(我認爲某些防火牆可能會阻止此行爲以防止端口掃描等)。所以,當服務器支持發送ICMP時,你的整個答案是正確的,只有一點例外。 – Zuljin 2011-04-28 20:54:58

1

操作系統不會因爲發生錯誤而關閉套接字。如果另一端消失,您可以繼續向其發送消息(但可能會收到更多錯誤)。