同一端口上的几个TCP服务器 [英] several TCP-servers on the same port

查看:182
本文介绍了同一端口上的几个TCP服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对我来说这看起来很奇怪。我可以在同一个端口上运行几个TCP服务器。

It looks very strange for me. I can run several TCP servers on the same port.

我使用Apache MINA库,代码如下:

I use Apache MINA library with following code:

IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.bind(new InetSocketAddress(80));

另一个程序已经使用了端口80。但我没有得到异常地址已经在使用中。使用netstat,我可以看到以下内容:

Port 80 is already used by another program. But I didn't get exception "Address already in use". With netstat I can see following:

C:\>netstat -oan |find /i "LIST"
  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       2220
  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       904
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       840

有人可以解释一下这种行为吗?

Could someone explain me such behaviour?

OS :Windows 7。

OS: Windows 7.

谢谢。

推荐答案

通常只有一个流程可以在Windows或任何其他操作系统(至少是主要操作系统)上侦听TCP端口。在Windows上,如果两个进程共享端口,您可能会收到错误代码10048。如果进程绑定到不同的接口地址,这将不适用(即使一个绑定到 INADDR_ANY 而另一个绑定到特定地址,它们不会发生冲突)。此外,如果 SO_REUSEADDR 已在第二个套接字上设置。

Normally only one process can listen on a TCP port, on Windows or any other OS (at least the major ones). On Windows you'd expect to get error code 10048 if two processes share the port. This won't apply if the processes are bound to different interface addresses (even if one is bound to INADDR_ANY and the other is bound to a specific address, they don't clash). Also, this doesn't apply if SO_REUSEADDR has been set on the second socket.

由于两个进程都绑定到 INADDR_ANY 并且您声称您的流程尚未设置 SO_REUSEADDR ,但这是一个难题。据我所知,有三种可能性:

Since both processes are bound to INADDR_ANY and you claim your process hasn't had SO_REUSEADDR set, however, this is a puzzle. As far as I can tell there are three possibilities:


  1. 基础库中的某些东西是设置 SO_REUSEADDR 默认情况下。

  2. 第二个套接字实际上是稍后打开的,它是指定 SO_REUSEADDR 的那个。

  3. Windows套接字层中有一个允许这样做的错误。

  1. Something in the underlying library is setting SO_REUSEADDR by default.
  2. The second socket was actually opened later and it's the one specifying SO_REUSEADDR.
  3. There is a bug in the Windows sockets layer which allowed this.

我发现没有软件是完美的,但是我真的很犹豫选择第三种选择,特别是如果你可以轻松复制它。我建议在启动进程之前和之后仔细观察 netstat 输出,并在此之前查看是否存在其他侦听器。此外,尝试识别其他进程并查看它是否相关(您可以在任务管理器中启用PID列)。

I realise no software is perfect, but I really hesitate to choose the third option, especially if you can easily reproduce it. I would suggest carefully watching netstat output before and after starting your process and seeing whether the other listener exists prior to that. Also, try to identify the other process and see whether it's related (you can enable the PID column in the task manager for that).

编辑

下面的评论者提醒我,我应该指出 SO_REUSEADDR 的行为确实因平台而异。 Windows允许使用该选项的新套接字强制绑定到与其他侦听套接字相同的端口,如果两个套接字都是TCP,则行为不确定,如上所述这里。在实践中,第二个套接字可能窃取了地址,但官方线似乎是行为未定义:

The commenter below has reminded me that I should point out that the behaviour of SO_REUSEADDR does differ across platforms. Windows allows new sockets using the option to forcibly bind to the same port as other listening sockets, with undetermined behaviour if the two sockets are both TCP, as discussed here. In practice the second socket probably "steals" the address, but the official line seems to be that the behaviour is undefined:


一旦第二个套接字已成功绑定,绑定到该端口的所有套接字的行为是不确定的。例如,如果同一端口上的所有套接字都提供TCP服务,则无法保证端口上的任何传入TCP连接请求都由正确的套接字处理 - 行为是不确定的。

Once the second socket has successfully bound, the behavior for all sockets bound to that port is indeterminate. For example, if all of the sockets on the same port provide TCP service, any incoming TCP connection requests over the port cannot be guaranteed to be handled by the correct socket — the behavior is non-deterministic.

Linux(和其他Unix变种)不允许两个TCP套接字共享同一个端口(如果旧的仍在侦听)。在这种情况下, SO_REUSEADDR 只允许新的socket绑定如果旧的一个是在TIME_WAIT(或许FIN_WAIT和CLOSE_WAIT状态,我必须检查)。

Linux (and other Unix variants) will not allow two TCP sockets to share the same port if the old one is still listening. In this case, SO_REUSEADDR only allows the new socket to bind if the old one is in TIME_WAIT (and perhaps the FIN_WAIT and CLOSE_WAIT states, I'd have to check that).

顺便说一下,当我第一次在Windows中遇到它时,我发现行为上的差异非常令人惊讶,但我自己测试了它,当然如果你设置<$两个套接字上的c $ c> SO_REUSEADDR 很可能同时成功绑定到完全相同的地址和端口。然而,我没有对这种情况下的确切行为进行过广泛的测试,因为在我的情况下它没有太大关系。

As an aside, I found the difference in behaviour quite surprising when I first came across it in Windows, but I've tested it myself and certainly if you set SO_REUSEADDR on both sockets it's quite possibly to bind successfully to exactly the same address and port simultaneously. I haven't done extensive testing on the exact behaviour in this situation, however, since in my case it didn't matter too much.

我不打算进入哪个平台正确,但肯定Windows行为导致安全问题,这就是为什么他们想出了 SO_EXCLUSIVEADDRUSE 选项来防止其他套接字强行绑定。我也似乎有人认为Windows版本应该被视为一个完全不同的选项,具有不同的行为,恰好具有相同的名称。

I'm not about to get into which platform is "correct", but certainly the Windows behaviour has lead to security issues which is why they came up with the SO_EXCLUSIVEADDRUSE option to prevent other sockets forcibly binding. I've also seem people of the opinion that the Windows version should be regarded as a completely different option, with different behaviour, which just happens to have the same name.

这篇关于同一端口上的几个TCP服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆