[英]several TCP-servers on the same port
It looks very strange for me. 对我来说看起来很奇怪。 I can run several TCP servers on the same port.
我可以在同一端口上运行多个TCP服务器。
I use Apache MINA library with following code: 我使用带有以下代码的Apache MINA库:
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.bind(new InetSocketAddress(80));
Port 80 is already used by another program. 端口80已被另一个程序使用。 But I didn't get exception "Address already in use".
但是我没有收到异常“地址已在使用中”。 With netstat I can see following:
使用netstat可以看到以下内容:
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. 操作系统:Windows 7。
Thanks. 谢谢。
Normally only one process can listen on a TCP port, on Windows or any other OS (at least the major ones). 通常,只有一个进程可以在Windows或任何其他OS(至少是主要的OS)上的TCP端口上侦听。 On Windows you'd expect to get error code 10048 if two processes share the port.
在Windows上,如果两个进程共享该端口,则期望得到错误代码10048。 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). 如果进程绑定到不同的接口地址(即使一个绑定到
INADDR_ANY
,而另一个绑定到一个特定的地址,则它们不会冲突),这将不适用。 Also, this doesn't apply if SO_REUSEADDR
has been set on the second socket. 另外,如果已在第二个套接字上设置了
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. 由于两个进程都绑定到
INADDR_ANY
并且您声称尚未设置SO_REUSEADDR
,所以这是一个难题。 As far as I can tell there are three possibilities: 据我所知,存在三种可能性:
SO_REUSEADDR
by default. SO_REUSEADDR
设置为SO_REUSEADDR
。 SO_REUSEADDR
. SO_REUSEADDR
的那个。 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. 我建议您在启动过程之前和之后仔细观察
netstat
输出,并查看在此之前是否存在其他侦听器。 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). 另外,尝试识别其他进程并查看其是否相关(您可以为此在任务管理器中启用PID列)。
EDIT 编辑
The commenter below has reminded me that I should point out that the behaviour of SO_REUSEADDR
does differ across platforms. 下面的评论者提醒我,我应该指出
SO_REUSEADDR
的行为在不同平台之间确实有所不同。 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 . Windows允许使用强制绑定到同一个端口侦听其它插座,用不确定的行为,如果这两个插座都是TCP,作为讨论的选项新的套接字这里 。 In practice the second socket probably "steals" the address, but the official line seems to be that the behaviour is undefined:
实际上,第二个套接字可能会“窃取”地址,但是官方的说法似乎是行为未定义:
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.
例如,如果同一端口上的所有套接字都提供TCP服务,则不能保证该端口上的任何传入TCP连接请求都可以由正确的套接字处理-该行为是不确定的。
Linux (and other Unix variants) will not allow two TCP sockets to share the same port if the old one is still listening. 如果旧的Linux套接字仍在侦听,则Linux(和其他Unix变体)将不允许两个TCP套接字共享同一端口。 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). 在这种情况下,如果旧套接字处于TIME_WAIT(也许是FIN_WAIT和CLOSE_WAIT状态,我必须检查一下),
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. 顺便说一句,当我第一次在Windows中遇到它时,我发现行为上的差异令人惊讶,但我已经对其进行了测试,并且可以肯定的是,如果您在两个套接字上都设置了
SO_REUSEADDR
,则很有可能成功绑定到完全相同的地址和端口同时。 I haven't done extensive testing on the exact behaviour in this situation, however, since in my case it didn't matter too much. 但是,我没有对这种情况下的确切行为进行过广泛的测试,因为在我看来,这并不太重要。
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. 我不会进入哪个平台是“正确的”,但是Windows行为肯定会导致安全问题,这就是为什么他们提出
SO_EXCLUSIVEADDRUSE
选项来防止其他套接字被强制绑定的原因。 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. 我似乎也认为,Windows版本应被视为完全不同的选项,具有不同的行为,而恰好具有相同的名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.