2011-07-15 57 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'不能解决问题,它隐藏了它。 –

相关问题