18

下图显示了 2 个尝试并成功将侦听套接字(服务器)绑定到我本地计算机上的端口 10000 的进程:

Sysinternals 显示端口 10000 上的 2 个绑定

这是 netstat 的输出(用于确认):

netstat -a -n | find "10000"
  TCP    0.0.0.0:10000          0.0.0.0:0              LISTENING
  TCP    0.0.0.0:10000          0.0.0.0:0              LISTENING
  TCP    [::]:10000             [::]:0                 LISTENING

(注意:javaw.exe 进程是第一个在 10000 上打开侦听套接字的进程)。

虽然我知道多个进程确实可以在同一个端口( SO_REUSEADDR)上侦听的情况,但在我的特定场景中有些事情困扰着我:

  1. 在我的应用程序中,我特别对 .NET 说我想要一个独占侦听套接字 ( SO_EXCLUSIVEADDRUSE)

    listener = new TcpListener(adr, ipport);
    listener.ExclusiveAddressUse = true;
    
  2. .NET 不会抛出端口已在使用中的任何异常/错误/通知。事实上,它实际上相信一切都很顺利。

  3. listener.AcceptTcpClient()从那时起,我的服务器应用程序永远不会从呼叫中唤醒。应该与服务器通信的客户端应用程序接收到一个有效的连接,但无法与“我的”服务器通信(假设是因为它建立了与不讲其“协议”的“其他”进程的连接)。

如果有人想尝试重现我的发现:第二个过程是 Eclipse (PHP) 的“Helios”版本。但是具体的进程在这里并不重要:如果一个进程可以在操作系统下做奇怪的事情,那么其他进程也可以。

关于如何获得错误或完全防止这种情况(通过附加参数)的任何建议?

4

4 回答 4

4

您在评论中发布的MSDN 链接似乎回答了您的问题。

它与绑定到通配符 IP 端点(0.0.0.0ip4;::用于 ip6 或IPEndpoint.ANY)的 java 应用程序有关。我假设adr上面代码片段中的变量是特定的 IP 地址,而不是通配符地址。

看看那篇文章中的表格。它列出了尝试使用不同的套接字选项组合再次绑定到特定或通配符端点的结果。

简而言之,Java 代码在没有套接字选项的情况下绑定在通配符0.0.0.0端点上。SO_EXCLUSIVEADDRUSE矩阵显示,发生这种情况时,您可以成功绑定到特定地址并通过请求独占地址使用。

如果您尝试使用通配符进行绑定,该表显示调用将失败。

于 2013-01-18T03:06:30.280 回答
1

不知道为什么它没有抛出异常。虽然,文档说TcpListener的构造函数并没有真正验证端口是否打开,因此,它只ArgumentException在端口号无效时抛出。当端口已经被另一个进程打开时,其他方法,比如Start将抛出一个SocketExceptionwith ErrorCodeset to (10048) (参见Start 方法Socket Error Codes)。WSAEADDRINUSE

为了防止这种情况,调用Start并捕获SocketException或使用命名空间System.Net.NetworkInformation来查询所有使用的端口并确定特定端口是否可用,如以下答案所示:In C#, how to check if a TCP port is available?

于 2013-01-08T02:20:58.140 回答
0

我相信你需要真正启用 TCP 端口共享 - 我现在在我的手机上,所以我现在能做的最好的就是删除一个链接: Net.TCP 端口共享

于 2012-11-14T16:47:45.973 回答
0

http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.exclusiveaddressuse.aspx - 请注意有关 ExclusiveAddressUse 的一些操作系统差异。尝试以管理员身份运行。另一个想法,尝试进入您的计算机管理 -> 服务并停止 Net.Tcp 端口共享服务。

于 2013-01-18T01:32:13.370 回答