我们可以在收到应用程序级别确认后重置TCP连接吗?

时间:2016-06-23 13:36:46

标签: sockets networking tcp

我正在研究重置TCP连接作为REGEXP问题的解决方案。

让我们使用以下请求 - 回复协议作为示例:

  1. 客户端打开与服务器的连接。
  2. 客户端发送请求。
  3. 服务器回复。
  4. 服务器关闭。
  5. 客户也关闭。
  6. 这会在服务器上导致TIME_WAIT状态。作为变体,客户可以先关闭。然后,TIME_WAIT落在客户端上。

    我们不能用以下内容替换第4步和第5步吗?

    1. 客户端重置。
    2. 服务器重置以响应传入的重置。
    3. 这似乎是一种避免TIME_WAIT问题的方法。服务器已经证明它通过发送回复来接收和处理请求。一旦客户得到回复,连接就是可以消耗的,并且可以随时消失。

      这是个好主意吗?

2 个答案:

答案 0 :(得分:1)

唯一的问题是服务器不知道客户端是否收到了所有内容。情况不明确:客户端连接重置是因为客户端收到了整个回复,还是因为其他原因而被重置?

添加应用程序级别确认无法可靠地解决问题。如果客户端确认,然后立即中止,客户端无法确定服务器是否收到该确认,因为中止关闭会丢弃未传输的数据。而且,即使传输数据,由于连接不可靠,也可能丢失数据;一旦连接中止,TCP堆栈将不再提供该数据的重传。

常规的非中止情况通过让客户端和服务器TCP堆栈独立于应用程序执行来处理最终仪式来解决问题。

因此,总而言之,如果我们关心的是客户端收到其回复,并且服务器不关心是否成功,则中止是可以的:在许多情况下不是不合理的假设。

我怀疑你在服务器上的TIME_WAIT错误。

如果您按照以下顺序执行单个基于TCP的客户端 - 服务器事务,则TIME_WAIT位于客户端:

  1. 客户端启动与服务器的活动连接

  2. 客户端向服务器发送请求。

  3. 客户端半关闭连接(即发送FIN)

  4. 服务器读取客户请求直到EOF(FIN段)

  5. 服务器发送回复并关闭(生成FIN)

  6. 客户读取对EOF的回复

  7. 客户关闭。

  8. 由于客户端是第一个发送FIN的客户端,因此它进入TIME_WAIT。

    诀窍是客户端必须首先关闭发送方向,服务器通过读取整个请求来同步它。换句话说,您使用流边界作为消息边界。

    您要做的是完全在应用程序协议内部进行请求构建,而根本不使用TCP框架。也就是说,服务器在没有客户端关闭的情况下识别客户端消息的结束,同样客户端解析服务器响应而不关心阅读直到结束。

    即使您的协议是这样的,您仍然可以通过半关闭舞蹈例程的动作。在检索到客户端请求之后,服务器可以继续读取其套接字并丢弃字节,直到它读取所有内容,即使没有预期的字节。

答案 1 :(得分:1)

我会说:不,这不是一个好主意。每个可能的解决方案最终都会遇到TIME_WAIT最终解决的相同“问题”:甲方如何确认连接的结束(或确认另一方最终确认连接的结束),知道该方B得到了确认?答案永远是:它肯定不会确切知道。

你说:

  

服务器已经证明它通过发送回复来接收和处理请求

...但如果该回复丢失怎么办?服务器现在已经清理了会话的一面,但客户端将永远等待该回复。

乍一看,TCP状态机可能看起来过于复杂,但是这一切都是有充分理由的。