半建立连接
对于半建立的连接,我的意思是客户端调用connect()
成功返回的连接,但服务器调用accept()
没有成功。这可以通过以下方式发生:客户端调用connect()
,从而将SYN
数据包发送到服务器。服务器进入状态并向客户端SYN-RECEIVED
发送SYN-ACK
数据包。这会导致客户端回复ACK
,进入状态ESTABLISHED
并从connect()
调用中返回。如果 finalACK
丢失(或由于服务器上的完整接受队列而被忽略,这可能是更可能的情况),服务器仍处于状态SYN-RECEIVED
并且accept()
不会返回。由于与SYN-RECEIVED
状态相关的超时SYN-ACK
将被重新发送,允许客户端重新发送ACK
. 如果服务器最终能够处理ACK
,它也会进入状态ESTABLISHED
。否则它将最终重置连接(即向RST
客户端发送一个)。
您可以通过在单个侦听套接字上启动大量连接来创建此场景(如果您不调整 backlog 和tcp_max_syn_backlog
)。有关更多详细信息,请参阅此问题和本文。
实验
我进行了几次实验(使用此代码的变体)并观察到一些我无法解释的行为。所有实验都是使用 Erlanggen_tcp
和当前的 Linux 进行的,但我强烈怀疑答案并不特定于这个设置,所以我试图在这里保持更通用。
connect()
-> 等待 -> send()
->receive()
我的出发点是从客户端建立连接,等待 1 到 5 秒,向服务器发送“Ping”消息并等待回复。使用此设置,我观察到当我有一个半建立的连接时receive()
失败并出现错误。在半建立连接closed
期间从未出现错误。您可以在此处send()
找到有关此设置的更详细说明。
connect()
-> 漫长的等待 ->send()
要查看,如果在半建立的连接上发送数据时出现错误,我在发送数据前等待了 4 分钟。这 4 分钟应涵盖与半建立连接相关的所有超时和重试。仍然可以发送数据,即send()
返回没有错误。
connect()
->receive()
接下来我测试了如果我只receive()
用很长的超时时间(5 分钟)调用会发生什么。我的期望是closed
在半建立的连接中出现错误,就像在原始实验中一样。唉,什么也没发生,没有抛出错误,接收最终超时。
我的问题
- 我所说的半建立连接有一个通用名称吗?
- 为什么
send()
半建立连接成功? receive()
如果我先发送数据,为什么 a only 会失败?
欢迎任何帮助,尤其是详细解释的链接。