考虑TCP的三次握手。它解释为here。
现在上面的文章提到双方可能会同时尝试连接,在这种情况下三方握手可以正常工作。
我们可以使用套接字api模拟这种情况吗? 我们通常使用套接字编码的是被动打开(服务器)和活动打开(客户端)?
答案 0 :(得分:15)
可以使用套接字API同时打开TCP。正如尼古拉所提到的,这是一个执行以下序列的时间问题,使得初始SYN彼此交叉。
bind addr1, port1
connect addr2, port2
bind addr2, port2
connect addr1, port1
以下是我使用单个Linux主机实现同步打开的方法。
使用netem
降低环回接口的速度tc qdisc add dev lo root handle 1:0 netem delay 5sec
运行netcat
两次
netcat -p 3000 127.0.0.1 2000
netcat -p 2000 127.0.0.1 3000
两个netcat进程相互连接,从而产生单个TCP连接
$ lsof -nP -c netcat -a -i # some columns removed
COMMAND PID NAME
netcat 27911 127.0.0.1:2000->127.0.0.1:3000 (ESTABLISHED)
netcat 27912 127.0.0.1:3000->127.0.0.1:2000 (ESTABLISHED)
这是tcpdump向我展示的内容(为清晰起见编辑了输出)
127.0.0.1.2000 > 127.0.0.1.3000: Flags [S], seq 1139279069
127.0.0.1.3000 > 127.0.0.1.2000: Flags [S], seq 1170088782
127.0.0.1.3000 > 127.0.0.1.2000: Flags [S.], seq 1170088782, ack 1139279070
127.0.0.1.2000 > 127.0.0.1.3000: Flags [S.], seq 1139279069, ack 1170088783
答案 1 :(得分:4)
作为参考,除了来自sigjuice和Nikolai的可靠答案之外,还提供一个示例,使用python可以轻松实现同步打开。在两个不同的python解释器中,执行:
>>> import socket
>>> s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s1.bind(('localhost', 1111))
>>> s1.connect(('localhost', 2222))
>>> s1.send('hello')
5
>>> s1.recv(5)
'world'
和
>>> import socket
>>> s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s2.bind(('localhost', 2222))
>>> s2.connect(('localhost', 1111))
>>> s2.recv(5)
'hello'
>>> s2.send('world')
5
(连接调用必须在两个绑定调用都返回后才会出现)
答案 2 :(得分:3)
我们做被动服务器和活动客户端,因为它易于理解,[相对]易于实现,并且易于编码。想想商店和顾客,我们会遇到以下情况之一:
由于服务器被动地等待客户端连接,因此很容易预测何时可以进行连接。不需要预先协议(除服务器地址和端口号之外)。
另一方面,同时打开会受到双方连接超时的影响,即必须仔细协调才能进行连接,以便SYN
交叉“飞行”。这是TCP协议的一个有趣的工件,但我认为它在实践中没有任何用处。
您可以尝试通过打开套接字,将其绑定到端口(以便另一方知道连接到哪里)以及尝试连接来尝试模拟此操作。双方都是对称的。可以尝试使用带有-p
选项的netcat。你必须要快得多:)