【问题标题】:Why RST was Sent When No Close() or Shutdown() Called?为什么在没有调用 Close() 或 Shutdown() 时发送 RST?
【发布时间】:2015-10-26 19:11:01
【问题描述】:

我们正在使用 LoadRunner 对基于 tcp 的多线程服务器应用程序进行压力测试。最近遇到一个烦人的问题:

客户端在一些周期后收到错误报告 - “10054 - 对等方重置连接”。通过从客户端捕获数据包,我们发现客户端从服务器接收到 RST。

奇怪的是我们没有从服务器端调用任何 close() 或 shutdown()(出于测试目的),客户端仍然收到 RST 数据包和 10054 错误?!!

以下是我抓到的数据包:

  1. 5395 77.335317000 192.168.11.232 192.168.11.30 TCP 62 27124→10000 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 SACK_PERM=1
  2. 5656 77.356679000 192.168.11.30 192.168.11.232 TCP 60 10000→27124 [SYN, ACK] Seq=0 Ack=1 Win=14600 Len=0 MSS=1460
  3. 5657 77.356684000 192.168.11.232 192.168.11.30 TCP 54 27124→10000 [ACK] Seq=1 Ack=1 Win=65535 Len=0
  4. 5776 77.359276000 192.168.11.232 192.168.11.30 TCP 1514 [重组 PDU 的 TCP 段]
  5. 5778 77.359286000 192.168.11.232 192.168.11.30 HTTP/XML 332 POST /AddressBookController.php HTTP/1.1
  6. 5901 77.368227000 192.168.11.30 192.168.11.232 TCP 60 10000→27124 [RST] Seq=1 Win=0 Len=0

这是我的问题,任何帮助将不胜感激!

第一季度。为什么服务器会发送RST给客户端当它甚至没有从服务器端调用任何close()或shutdown()到套接字时

第二季度。 [重复 Q1,请跳过]当客户端和服务器都没有调用任何 close() 或关闭时,服务器在什么情况下会发送 RST?

第三季度。我可以重新编译内核并在 TCP 堆栈中打印一些日志吗?我想知道它发送RST数据包时发生了什么。

[更新]
将listen(BACKLOG) 从 BackLog=100 增加到 BackLog=1000,将大大减少错误从大约 50/小时到 1~2/10 小时。为什么?

[更新2]
1.这是一个接受soap请求并返回的gSOAP服务器 向客户端发送 1~2 KB 的数据。
2. 我们检查了来自客户端的数据包,没有来自服务器的 FIN 标志,这证明服务器从不调用任何 close() 或 关机()。
3. 我们使用 LoadRunner 做新闻测试,有 400 个用户发出并行的肥皂请求,频率是每人 8 万个请求 小时平均值。
4. Packet 4内容无异常,以下为部分内容

POST /AddressBookController.php HTTP/1.1
Host: 192.168.11.30:10000
User-Agent: gSOAP/2.7
Content-Type: text/xml; charset=utf-8
Content-Length: 1470
Connection: close
Cookie: sessionId=a23b15dcc14bb1d8f9f6bf3c4ed728d90c4c3939143866821152918211
SOAPAction: ""

<?xml version="1.0" encoding="UTF-8"?>
......

【问题讨论】:

  • 数据包 4 中有什么?

标签: linux multithreading sockets tcp


【解决方案1】:

第一季度。为什么服务器会发送 RST 给客户端,而它甚至没有调用任何 close() 或 shutdown() 到套接字?

因为服务器决定关闭连接,但客户端继续发送。或者,服务器在还有未读数据时关闭了它的套接字。

第二季度。当客户端和服务器都没有调用任何 close() 或关闭时,服务器会在什么情况下发送 RST?

这又是同一个问题。

第三季度。我是否可以重新编译内核并在 TCP 堆栈中打印一些日志?我想知道它发送RST数据包时发生了什么。

不,你想知道在它发送 RST 数据包之前发生了什么。

问题似乎出在您的客户身上。它肯定会在某个时候关闭连接。

编辑 在这种情况下,您似乎在数据包 #4 中发送了一些奇怪的东西(非 HTTP),这导致服务器关闭了连接。这是什么?

【讨论】:

  • 但是在我们的例子中,我们没有在服务器端调用 close() 或 shutdown。此外,我们检查了没有未读数据,因为我将 close() 替换为 while(read()) 之类的东西。那怎么会发生呢?包有什么问题吗?
  • 最可能的原因是与会话或状态数据相关的未处理动态元素。过期或不适当的数据会被交给服务器,然后服务器会因为无效而终止连接。
  • @JamesPulley 这确实会导致发送 RST,但是看到这六个数据包,我看不出它们有什么问题,它们是从客户端捕获的。
  • 这是什么服务器? netstat 在服务器主机上显示 RST 后的连接状态(如果有)是什么?你真的写过自己的 HTTP 服务器吗?因为只有这样才能知道它是调用close() 还是shutdown(),除非你有调试器或系统调用跟踪。
  • 查看相关连接的 HTTP 日志和 HTTP 错误日志。您可能会发现一个很好的错误文本,例如“无效的会话标识符”,它会指出重置的原因。
【解决方案2】:

从(以前相关的)RFC 2616 引用您的“数据包 4”:

HTTP/1.1 为发送者定义了“关闭”连接选项,以发出响应完成后连接将被关闭的信号。例如,

Connection: close

所以你似乎得到了你所要求的。

【讨论】:

  • 可能是内容格式错误,但由于服务器不是 HTTP 服务器,这意味着它不会通过 HTTP 选项解析其内容,也不会调用 close() 或 shutdown( ),所以这个项目似乎不是原因,对吧?
  • @Steve:为什么不看看客户端不发送这条线会发生什么?
猜你喜欢
  • 2013-04-10
  • 2017-04-22
  • 1970-01-01
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多