在由服务器关闭的TCP连接上发送数据时的行为不一致

时间:2017-05-30 00:17:12

标签: c++ tcp client-server solaris-10

我在公司遇到了一个单元测试程序(Solaris上的C ++)。

它测试当客户端尝试通过服务器关闭的TCP连接向服务器发送msg时是否抛出错误。

情景:

Client                          Server
  |<----------Connected----------->|
  |                                |
  |          2 sec pause           |
  |                                |
  |<-----shutdown(SHUT_RDWR)-------|
  |<-----------close---------------|
  |                                |
  |          2 sec pause           |
  |                                |
  |-------------send-------------->|
  |-------------send-------------->|

一般行为:第一个send()返回否。写入套接字的字节数。第二个send()失败,即返回-1。这是预期的行为。

行为不一致send()都通过,导致测试用例失败。

注意:两个send()之间没有延迟。

SunOS 5.10(64位)

上的行为不一致

问题1:有人可以解释一下上面描述的“一般行为”吗?为什么第一send()没有失败?为什么第二个send()失败了?

我对TCP知之甚少所以进行了一些研究并猜测可能在close()之后服务器端的TCP堆栈处于FIN-WAIT-2状态,并且在close()状态之后收到第一个消息后{ {1}}(通过第一个send())它以ACK响应,也许在此ACK中它会通知客户端停止发送更多的消息?

问题2:关于“行为不一致” - 第二个send()有时不会失败 - 为什么?

是否因为在收到第一个消息的ACK之前发送了第二个消息? (这种解释当然取决于第一个问题的假设)

注意:客户端和服务器位于同一台计算机上,而snoop没有帮助。

1 个答案:

答案 0 :(得分:2)

  

我在公司遇到了一个单元测试程序(Solaris上的C ++)。

     

它测试当客户端尝试通过服务器关闭的TCP连接向服务器发送msg时是否抛出错误。

应该没有这样的测试。您不测试平台,而是测试应用程序。

  

一般行为:第一个send()返回no。写入套接字的字节数。第二个send()失败,即返回-1。这是预期的行为。

不,不是。 可能通常的行为,但没有任何规范要求它作为正确的行为。所以测试再次无效。

  

行为不一致:send()都通过,导致测试用例失败。

这可能随时发生,不应视为失败。

  

注意:两个send()之间没有延迟。

这使得第二次发送更有可能成功,实际上两个发送将合并为单个出站TCP段,或者更好的是两个发送都适合套接字发送缓冲区并且还没有发送到所有

  

SunOS 5.10(64位)

上的行为不一致

这很正常。

  

问题1:有人可以解释一下上面描述的“一般行为”吗?为什么第一次发送()没有失败?为什么第二次发送()失败?

为什么?如果没有任何规范强制要求这些行为,这里没有任何解释。

  

我对TCP知之甚少所以进行了一些研究并猜测可能在close()之后服务器端的TCP堆栈处于FIN-WAIT-2状态,并且当它在close()之后收到第一个msg时(通过第一个send())它以ACK响应,也许在这个ACK中它通知客户端停止发送更多的消息?

这不正确,但详细说明这一点毫无意义,因为整个测试无效且应该删除。

  

问题2:关于“不一致的行为” - 第二次发送()有时不会失败 - 为什么?

见上文。

  

是否因为在收到第一个msg的ACK之前发送了第二个消息? (这种解释当然取决于第一个问题的假设)

您需要了解send()是异步的。它所做的只是套接字发送缓冲区中的缓冲区数据。在send()返回时,数据可能永远不会被发送到对等体。这是另一个因素足以使测试完全无效。

  

注意:客户端和服务器位于同一台计算机上

如果可能的话,这只会使测试更加毫无意义。