2009-05-22 254 views
12

我目前正在維護一些網絡服務器軟件,我需要執行大量的I/O操作。當在套接字上使用時,調用read(),write(),close()shutdown()有時可能會引發ENOTCONN錯誤。這個錯誤究竟意味着什麼?什麼是會觸發它的條件?我永遠無法在本地重現它,但有用戶可以。什麼導致ENOTCONN錯誤?

現在我只是忽略了ENOTCONN當提出close()shutdown()因爲它似乎無害,但我不完全確定。

編輯:

  • 我絕對肯定的connect()調用成功。我檢查它的返回值。
  • ENOTCONN最常見的是close()shutdown()。我只是很少見到read()write()籌集ENOTCONN
+0

什麼操作系統?我正在跟蹤一箇舊Solaris 10系統上的類似問題。謝謝。 – Nemo 2011-12-13 02:27:56

+0

大部分是FreeBSD。同時,我發現FreeBSD中有內核錯誤,可能會導致close()和shutdown()在處理Unix域套接字時錯誤地返回ENOTCONN。 Solaris也有各種內核錯誤w.r.t. Unix域套接字,儘管我只在connect()中觀察到錯誤。 – Hongli 2011-12-13 08:52:00

回答

13

如果您確定TCP連接的任何內容都沒有關閉連接,那麼在我看來就像遠程端正在關閉連接。正如其他人指出的那樣,僅僅意味着插座沒有連接。這並不一定意味着connect失敗。該插座可能以前已連接,它只是不是在通話時導致ENOTCONN

這不同於:

  • ECONNRESET:所述連接的另一端發送的TCP重置分組。如果另一端拒絕連接,或者不承認連接已經連接等,則可能發生這種情況。
  • ETIMEDOUT:這通常只適用於connect。如果連接嘗試在系統相關的時間內不成功,則可能發生這種情況。

EPIPE有時可以通過一些插座相關係統返回或多或少一樣ENOTCONN條件下調用。例如,在某些系統上,EPIPEENOTCONN在由send返回時是同義詞。

雖然shutdown返回ENOTCONN並不罕見,但由於此功能應該拆除TCP連接,所以我很驚訝地看到close返回ENOTCONN。它真的不應該那樣做。

最後,如dwc提到的,EBADF不適用於您的場景,除非您正在嘗試對已經爲close d的文件描述符執行某些操作。使套接字斷開連接(即,TCP連接已斷開)與關閉與該套接字關聯的文件描述符不同。

0

傳輸端點沒有連接

插座與面向連接的協議相關聯,並且還沒有被連接。這通常是一個編程缺陷。

來源:http://www.wlug.org.nz/ENOTCONN

+1

我知道錯誤的名稱,但它是什麼意思*?這個傳輸端點是指什麼?這與EPIPE,ECONNRESET和ETIMEDOUT有什麼不同? – Hongli 2009-05-22 21:24:09

+0

我想你只是沒有調用connect()或沒有檢查connect()是否成功。 – 2009-05-22 21:26:55

+0

我做到了,它成功了。報告此問題的用戶觀察到read()和write()工作得很好,但在shutdown()和close()時間引發ENOTCONN。我無法在本地複製它,而且大多數用戶也不會遇到此問題。 – Hongli 2009-05-22 21:29:53

0

如果你確定你已經在第一時間正確連接,ENOTCONN是最有可能被要麼fd引起您的最終被關閉,而(在另一個線程吧?)您處於請求的中間,或者處於請求中間時連接斷開。

無論如何,這意味着套接字未連接。繼續並清理該套接字。它已經死了。沒問題,撥打close()shutdown()就可以了。

1

我相信ENOTCONN被返回,因爲shutdown()不應該返回ECONNRESET或其他更準確的錯誤。

假設對方「剛」關閉了連接是錯誤的。在TCP級別上,另一方只能半連接(或中止連接)。如果雙方都執行shutdown()(或close()),則連接是完全關閉的。如果雙方都這樣做,shutdown()實際上對他們都成功了!

問題是關機()不是不是成功地在普通(半)關閉連接,既不是第一個關閉它,也不是第二個。 - 根據POSIX文檔中關於shutdown()所列的錯誤,ENOTCONN是最不合適的,因爲其他人指出傳遞給shutdown()(或處理請求的本地資源問題)的參數有問題。

那麼發生了什麼?現在,在涉及的兩方之間的某個NAT設備可能已經放棄了關聯併發送出RESET數據包作爲反應。重置連接對IPv4來說非常普遍,您可以在代碼中的任何地方獲取它們,甚至在shutdown()中將其屏蔽爲ENOTCONN。

編碼錯誤也可能是原因。例如,在一個非阻塞套接字上,connect()可以返回0而不指示連接成功。

1

這是因爲,在關閉()套接字時,套接字緩衝區中的數據等待被傳遞給關閉()或關閉()其接收套接字的遠程方。 我並沒有完全理解套接字是如何工作的,我只是一個noob,我甚至沒有找到執行這個「關閉」功能的文件,但是看到幾乎沒有整個套接字的用戶手冊。開始嘗試所有的可能性,直到我在「受控」環境中得到錯誤。這可能是別的東西,但是經過大量嘗試,這些都是我選定了解釋:

  • 如果你發送的數據遠程端關閉了連接之後,當你關機(),你的錯誤。
  • 如果您在遠程端關閉連接之前發送了數據,但在另一端沒有收到(),您可以shutdown()一次,下一次嘗試shutdown()時出現錯誤。
  • 如果你沒有發送任何數據,只要遠程端不關閉(),你可以關閉所有你想要的時間。一旦遠程端有shutdown(),如果你嘗試shutdown()並且套接字已經shutdown(),你會得到錯誤。