半建立连接
我所谓的半建立连接是指客户端调用connect()
成功返回,但服务器调用accept()
失败。这可能会发生以下方式:客户端调用connect()
,导致向服务器发送一个SYN
数据包。服务器进入状态SYN-RECEIVED
并向客户端发送一个SYN-ACK
数据包。这将导致客户端回复ACK
,进入状态ESTABLISHED
并从connect()
调用中返回。如果最终的ACK
丢失(或由于服务器上的完整接受队列而被忽略,这可能是更可能的情况),则服务器仍处于状态SYN-RECEIVED
,accept()
不会返回。由于与SYN-RECEIVED
状态相关联的超时,SYN-ACK
将被重新发送,允许客户端重新发送ACK
。如果服务器能够最终处理ACK
,它也将进入状态ESTABLISHED
。否则,它将最终重置连接(即向客户端发送一个RST
)。你可以通过在单个侦听套接字上启动大量连接(如果您不调整backlog和tcp_max_syn_backlog)来创建此场景。有关更多详细信息,请参见this questions和this article。
实验
我进行了几项实验(使用this code的变体),并观察到一些无法解释的行为。所有实验都是使用Erlang的gen_tcp
和当前的Linux执行的,但我强烈怀疑答案不特定于此设置,因此我在这里尝试保持更加通用。
connect()
->等待->send()
->receive()
我的起点是建立一个从客户端到服务器的连接,等待1到5秒钟后发送一个“Ping”消息到服务器并等待回复。在这种设置下,当我有一个半建立的连接时,我观察到receive()
失败并出现错误closed
。在半建立的连接上,send()
从未出现过错误。您可以在此处找到更详细的描述。
connect()
-> 长时间等待 -> send()
为了查看是否可以在半建立的连接上发送数据而出现错误,我等待了4分钟才发送数据。4分钟应该涵盖与半建立连接相关的所有超时和重试。发送数据仍然是可能的,即send()
返回而没有错误。
connect()
-> receive()
接下来我测试了只使用非常长的超时时间(5分钟)调用receive()
会发生什么。我的期望是对于半建立连接会收到一个closed
错误,就像在原始实验中一样。但遗憾的是,没有任何反应,也没有抛出错误,最终receive()
超时。
我的问题
- 半建立连接是否有通用名称?
- 为什么在半建立连接上执行
send()
操作成功? - 为什么只有在发送数据后才执行
receive()
操作会失败?
任何帮助,特别是详细解释的链接,都将受到欢迎。
connect()
-> 长时间等待 ->send()
-> 等待 ->send()
这样的情况,您会期望看到错误吗? - jvfconnect()
-> 等待 ->send()
-> 短暂等待 -> 第二个send()
失败了! - jvf