使用半连接建立我的意思是客户对connect()
的呼叫成功返回的连接,但服务器呼叫accept()
没有。这可以通过以下方式发生:客户端调用connect()
,从而生成到服务器的SYN
数据包。服务器进入状态SYN-RECEIVED
并向客户端发送SYN-ACK
数据包。这会导致客户端回复ACK
,进入状态ESTABLISHED
并从connect()
调用返回。如果最终ACK
丢失(或忽略,由于服务器上的完整接受队列,这可能是更可能的情况),服务器仍处于状态SYN-RECEIVED
和{{1} }不回来。由于与accept()
状态相关联的超时,SYN-RECEIVED
将重新发送,允许客户端重新发送SYN-ACK
。如果服务器最终能够处理ACK
,它也将进入状态ACK
。否则它最终会重置连接(即向客户端发送ESTABLISHED
)。
您可以通过在单个侦听套接字上启动 lots 连接来创建此方案(如果您不调整积压和RST
)。有关详细信息,请参阅this questions和this article。
我进行了几次实验(this code的变化)并观察了一些我无法解释的行为。所有使用Erlang' tcp_max_syn_backlog
和当前Linux执行的实验,但我强烈怀疑答案并非特定于此设置,所以我试图在这里保持一般性。
gen_tcp
- >等待 - > connect()
- > send()
我的出发点是从客户端建立连接,等待1到5秒,然后发送" Ping"消息到服务器并等待回复。通过此设置,我发现receive()
在我建立半连接时失败并显示错误receive()
。在{half}建立的连接上closed
期间从未出现过错误。您可以找到有关此设置的更详细说明here。
send()
- >漫长的等待 - > connect()
要看,如果我在半连接的连接上发送数据时会出错,我会在发送数据前等待4分钟。 4分钟应涵盖与半连接相关的所有超时和重试。仍然可以发送数据,即send()
无错误地返回。
send()
- > connect()
接下来,我测试了如果我只用很长的超时(5分钟)调用receive()
会发生什么。我的期望是在半成熟的连接中得到receive()
错误,就像在原始实验中一样。唉,没有任何事情发生,没有错误被抛出,接收最终超时。
closed
成功?send()
只有在我先发送数据时才会失败?欢迎任何帮助,尤其是详细解释的链接。
答案 0 :(得分:5)
从客户端的角度来看,会话已完全建立,它发送SYN,返回SYN / ACK并发送ACK。只有在服务器端,您才有半成熟的状态。 (即使它从服务器获得重复的SYN / ACK,它也会重新确认,因为它处于已建立的状态。)
此会话中的send
运行正常,因为就客户端而言,会话已建立。为了成功,远端不需要确认发送的数据(当数据被复制到内核缓冲区时发送系统调用完成),但见下文。
我相信这里发送的实际 会在连接上产生错误(可能是RST),因为接收系统无法在尚未完成建立的会话上确认数据。我的猜测是任何系统调用引用客户端上的套接字,发送后发送加上短暂的延迟(即当RST有机会返回时)将导致错误。
接收本身永远不会导致错误,因为客户端不需要为接收做任何事情(我的意思是TCP协议);它只是在等待。但是一旦你发送了一些数据,你就迫使服务器方面了:它已经完成了会话建立(在这种情况下它可以接受数据)或者它必须发送一个重置(我的猜测在这里它不能“持有” “未完全建立的会话未送达的数据。”