如何检查是否已在侦听TCP端口?

时间:2012-06-05 22:12:25

标签: c++ c winapi sockets tcp

我有一个充当HTTP服务器的第三方库。我传递了一个地址和端口,然后用它来监听传入的连接。该库以这样的方式进行侦听,即它不会接收端口的独占使用并解决它所绑定的问题。结果,我可以多次在同一个端口上听。

我需要在同一个进程中运行此HTTP服务器的多个实例。每个实例都有一个默认端口,但如果该端口不可用,则应使用下一个可用端口。这是我的问题所在;我最终可以在同一个端口上监听两个HTTP服务器。

我无法更改HTTP服务器的代码,如果无法侦听我提供的端口,HTTP服务器将不会提醒我,因此我必须能够在启动前检查端口是否已被使用每个HTTP服务器。我已经尝试通过绑定自己的套接字来检查端口是否已被监听,SO_REUSEADDR设置为FALSE且SO_EXCLUSIVEADDRUSE设置为TRUE,但是当现有HTTP服务器已经在该端口上侦听时,bind和listen调用都成功。

此HTTP服务器如何实现此效果,如何以这种方式准确检查是否正在侦听端口?

3 个答案:

答案 0 :(得分:5)

快速而脏的方法是尝试connect()到localhost上的端口。如果connect()调用成功,则表示当前正在侦听端口(由接收连接的任何人)。如果连接调用失败(特别是ECONNREFUSED),那么您可以非常确定没有人正在侦听该端口。

当然,这里有一个竞争条件:在你运行上述测试后,没有什么能阻止另一个程序突然进入并抓住端口,但在你自己绑定到端口之前。因此,您应该将测试结果视为一个提示而不是绝对规则,并且(希望)如果您稍后发现端口正在使用中,那么(希望)有一些方法可以处理它。

答案 1 :(得分:2)

使用端口号0.操作系统将选择一个空闲端口。

答案 2 :(得分:1)

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx解释了不同选项如何相互作用。

您还没有给我们足够的信息来告诉我们您的用例中究竟发生了什么,但我可以通过一个看起来像您所看到的任意用例

我们假设您使用的是Win 2003或更高版本,主NIC是10.0.0.1,并且所有内容都在同一个用户帐户下运行。

您的应用程序的第一个实例出现,您的测试代码尝试使用SO_EXCLUSIVEADDREUSE绑定10.0.0.1:12345。当然这很有效。

关闭套接字,然后告诉HTTP服务器监听端口12345.它使用SO_REUSEADDR绑定0.0.0.0:12345,这当然有效。

现在,您的应用程序的第二个实例出现了,您的测试代码尝试使用SO_EXCLUSIVEADDREUSE绑定10.0.0.1:12345。根据MSDN文章中的图表,这是有效的。

关闭套接字,然后告诉HTTP服务器监听端口12345.它使用SO_REUSEADDR绑定0.0.0.0:12345,这可以工作。

如果这是问题,假设您无法让HTTP服务器绑定特定地址,您可以在测试代码中使用0.0.0.0来解决问题。 (当然,如果它是其他数百个可能出现的问题之一,那么这个解决方案就不会起作用。)

如果你不知道HTTP服务器正在使用什么套接字选项,地址等,并且没有源代码,只需在调试器中运行它并断开相关的调用。

相关问题