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