一个 TCP 连接由这个元组 (local address, local port #, foreign address, foreign port #) 唯一标识。不需要local address 和foreign 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 的论文,不过在那种情况下,来源和外国会完全不同。