2011-07-15 56 views
2

在一個C++ Linux應用程序中,我調用socket(),bind()和listen()來創建服務器套接字。通常,如果應用程序啓動兩次(使用相同的服務器端口),則在第二個進程中,bind()將失敗並顯示EADDRINUSE錯誤。然而,現在我有一個情況下bind()顯然已成功,但隨後的listen()調用已拋出EADDRINUSE錯誤...爲什麼我會從bind()而不是從listen()獲得EADDRINUSE?

這可能是一種罕見的競爭條件,但我仍然對可能會發生第二個bind()成功但第二個listen()不成功的情況。有沒有人知道更多關於這種情況?

這是在32位RHEL 5.3上。

回答

3

不知道關於Linux,但在Windows中,如果一個通配符在調用bind()時指定IP(INADDR_ANY等)時,底層綁定可能會延遲,直到調用listen()connect(),因爲OS有更好的機會決定當時哪個網絡接口最適合使用。 bind()在這種情況下不會報告錯誤。

+0

謝謝,這似乎是解釋。顯然這些規則是: listen()實際上會保留內核中的端口,並且如果另一個進程在端口上調用了listen(),將引發EADDRINUSE; bind()並不保留端口,但如果另一個進程在端口上調用了listen(),則會引發EADDRINUSE – oliver

1

setsockopt(.... SOL_SOCKET, SO_REUSEADDR, ...)應該解決您的問題。

setsockopt(2)socket(7)

(至於爲什麼第二bind居然成功了,沒想到......其實這應該已經失敗過)

+0

二次失敗是一件好事。 –

+0

@Ben Voigt:當然,儘管我認爲在聽到'listen'之前,不僅''listen'應該失敗,而且已經'bind'。儘管雷米Lebeau關於_delayed綁定的理論可能是理由,但它無論如何都是完美的。 – Damon

+0

很高興我們同意。但是,'SO_REUSEADDR'不能解決問題,它隱藏了它。 –

相關問題