半成熟的TCP连接

时间:2016-06-23 17:01:37

标签: sockets tcp network-programming erlang gen-tcp

半成立连接

使用半连接建立我的意思是客户对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 questionsthis 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()错误,就像在原始实验中一样。唉,没有任何事情发生,没有错误被抛出,接收最终超时。

我的问题

  1. 我称之为半连接的连接是否有一个通用名称?
  2. 为什么半成立连接上的closed成功?
  3. 为什么send()只有在我先发送数据时才会失败?
  4. 欢迎任何帮助,尤其是详细解释的链接。

1 个答案:

答案 0 :(得分:5)

  1. 从客户端的角度来看,会话已完全建立,它发送SYN,返回SYN / ACK并发送ACK。只有在服务器端,您才有半成熟的状态。 (即使它从服务器获得重复的SYN / ACK,它也会重新确认,因为它处于已建立的状态。)

  2. 此会话中的send运行正常,因为就客户端而言,会话已建立。为了成功,远端不需要确认发送的数据(当数据被复制到内核缓冲区时发送系统调用完成),但见下文。

  3. 我相信这里发送的实际 会在连接上产生错误(可能是RST),因为接收系统无法在尚未完成建立的会话上确认数据。我的猜测是任何系统调用引用客户端上的套接字,发送后发送加上短暂的延迟(即当RST有机会返回时)将导致错误。

    接收本身永远不会导致错误,因为客户端不需要为接收做任何事情(我的意思是TCP协议);它只是在等待。但是一旦你发送了一些数据,你就迫使服务器方面了:它已经完成了会话建立(在这种情况下它可以接受数据)或者它必须发送一个重置(我的猜测在这里它不能“持有” “未完全建立的会话未送达的数据。”