如何将TCP连接重新连接到同一端口?

时间:2011-02-09 20:05:58

标签: linux networking tcp

Machine是RHEL 5.3(内核2.6.18)。

有些时候我在netstat中注意到我的应用程序有连接,当本地地址外部地址相同时建立了TCP连接。

Here其他人也报告了同样的问题。

症状与链接中描述的相同 - 客户端连接到本地运行的服务器的端口X端口。一段时间后,netstat显示客户端已从127.0.0.1:X连接到127.0.0.1:X

怎么可能?

修改01

同时打开导致问题(非常感谢Hasturkun)。从SYN_SENT状态转换为SYNC_RECEIVED

,您可以在classical TCP state diagram上看到它

2 个答案:

答案 0 :(得分:18)

这可能是由TCP同时连接引起的(提到on this post to LKML,另见here)。

程序循环尝试连接到动态本地端口范围内的端口(可以在/proc/sys/net/ipv4/ip_local_port_range中看到),以便在服务器没有侦听该端口时成功。

在足够多的尝试次数上,用于连接的套接字可以绑定到连接到的同一端口,由于前面提到的同时连接而成功。你现在神奇地有一个客户端连接到自己

答案 1 :(得分:13)

TCP连接由此元组(local address, local port #, foreign address, foreign port #)唯一标识。不要求local addressforeign address,或者甚至端口号不同(尽管这会非常奇怪)。但是,对于给定的元组,最多只有1个TCP连接具有相同的值。

当计算机连接到自身时,它的本地地址和外地地址几乎总是相同的。毕竟,“本地”方面和“外国”方实际上是同一台计算机。实际上,当发生这种情况时,您的计算机应该显示两个具有相同“本地”和“外部”地址的连接,但是反向端口号。例如:

$ ssh localhost

将导致两个连接看起来像这样:

$ netstat -nA inet | fgrep :22
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address        Foreign Address        State      
tcp        0      0 127.0.0.1:56039      127.0.0.1:22           ESTABLISHED 
tcp        0      0 127.0.0.1:22         127.0.0.1:56039        ESTABLISHED 

如您所见,本地地址和外地址相同,但端口号相反。此TCP连接的唯一元组是(127.0.0.1, 56039, 127.0.0.1, 22)。没有其他TCP连接具有这四个相同的字段。

您看到两个的事实是因为您的计算机是连接的两端。每一端都有自己的视图,其中一个是“外来的”,哪个是“本地的”。

您甚至可以在同一个端口上连接自己,虽然这不常见,但规范并未禁止。以下是Python中的示例程序:

import socket
import time

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 56443))
s.connect(('127.0.0.1', 56443))
time.sleep(30)

此代码有效,因为可以打开TCP连接的一种方法是让连接的另一端尝试同时打开一个连接。这被称为simultaneous SYN exchange,并且链接到StackOverflow的答案描述了它的内容。

我也有一篇关于using simultaneous SYN exchange to get through NAT的论文,但在这种情况下,来源和外国将完全不同。