如何才能将 TCP 连接返回到同一端口?
机器是 RHEL 5.3(内核 2.6.18)。
有时我在 netstat 中注意到我的应用程序已连接,当本地地址和外部地址相同时建立了 TCP 连接。
这里其他人也报告了同样的问题。
症状与链接中描述的相同 - 客户端连接到本地运行的服务器的端口 X 端口。一段时间后,netstat 显示客户端已从 127.0.0.1:X
到 127.0.0.1:X
连接,
这怎么可能?
编辑 01
同时打开导致了问题(非常感谢 Hasturkun)。您可以在从 SYN_SENT 状态转换到 SYNC_RECEIVED 状态的经典 TCP 状态图上看到它
Machine is RHEL 5.3 (kernel 2.6.18).
Some times I notice in netstat that my application has connection, established TCP connection when Local Address and Foreign Address are same.
Here same problem reported by someone else too.
The symptoms are same as described in link - client connects to port X port of server running locally. After some time netstat shows that client has connection from 127.0.0.1:X
to 127.0.0.1:X
How it's possible?
Edit 01
Simultaneous open is causing the problem (thanks a lot to Hasturkun). You can see it on classical TCP state diagram in transition from SYN_SENT state to SYNC_RECEIVED
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这可能是由于 TCP 同时连接造成的(在 LKML 的这篇文章中提到,另请参阅此处)。
当服务器正在运行时,程序可能会循环尝试连接到动态本地端口范围(可以在
/proc/sys/net/ipv4/ip_local_port_range
中看到)内的端口。没有监听该端口。经过足够多的尝试后,用于连接的套接字可能会绑定到正在连接的同一端口,由于前面提到的同时连接,该连接会成功。您现在神奇地拥有一个连接到自身的客户端
This may be caused by TCP simultaneous connect (mentioned on this post to LKML, see also here).
It's possible for a program looping on trying to connect to a port within the dynamic local port range (which can be seen in
/proc/sys/net/ipv4/ip_local_port_range
),to succeed while the server is not listening on that port.On a large enough number of attempts, the socket being used to connect may be bound to the same port being connected to, which succeeds due to previously mentioned simultaneous connect. You now magically have a client connected to itself
TCP 连接由这个元组
(本地地址,本地端口号,外部地址,外部端口号)
唯一标识。不要求本地地址
和外部地址
,甚至端口号不同(尽管这会非常奇怪)。但对于给定元组,最多有 1 个 TCP 连接具有相同的值。当计算机连接到自身时,它的本地地址和外部地址几乎总是相同的。毕竟,“本地”端和“外部”端实际上是同一台计算机。事实上,当发生这种情况时,您的计算机应该显示两个具有相同“本地”和“外部”地址但端口号相反的连接。例如:
将导致两个连接看起来像这样:
正如您所看到的,本地地址和外部地址相同,但端口号相反。此 TCP 连接的唯一元组是
(127.0.0.1, 56039, 127.0.0.1, 22)
。不会有其他 TCP 连接具有这四个相同的字段。您看到两个的事实是因为您的计算机是连接的两端。每一端都有自己的观点,哪一端是“外国”,哪一端是“本地”。
您甚至可以在同一端口上连接到自己,虽然这种情况并不常见,但规范并不禁止。下面是一个用 Python 编写的示例程序,它将执行此操作:
该代码之所以有效,是因为打开 TCP 连接的一种方法是让连接的另一端尝试同时与您打开一个连接。这称为同时 SYN 交换,并链接到 StackOverflow 答案描述了那是关于什么的。
我还有一篇关于使用同步 SYN 交换通过 NAT 的论文,但在这种情况下,来源和外国将完全不同。
A TCP connection is uniquely identified by this tuple
(local address, local port #, foreign address, foreign port #)
. There is no requirement thatlocal address
andforeign address
, or even that the port numbers be different (though that would be exceedingly strange). But there is at most 1 TCP connection that has the same values for a given tuple.When a computer connects to itself, it's local address and foreign address are almost always the same. After all, the 'local' side and 'foreign' side are actually the same computer. In fact, when this happens your computer should be showing two connections that have the same 'local' and 'foreign' addresses, but reversed port numbers. For example:
will result in two connections that look something like this:
As you can see, the local address and foreign addresses are the same, but the port numbers are reversed. The unique tuple for this TCP connection is
(127.0.0.1, 56039, 127.0.0.1, 22)
. There will be no other TCP connection that has these same four fields.The fact you see two is because your computer is both ends of the connection. Each end has its own view of which one is 'foreign' and which is 'local'.
You can even connect to yourself on the same port, and while this is not a common occurrence, it is not forbidden by the spec. Here is a sample program in Python which will do this:
This code works because one way in which it's possible to open a TCP connection is to have the other side of the connection try to open one with you simultaneously. This is known as simultaneous SYN exchange, and the linked to StackOverflow answer describes what that's about.
I also have a paper on using simultaneous SYN exchange to get through NAT, though in that case the source and foreign would be completely different.