我在WireShark中观察到以下场景:
我在这里看到的问题是,在[FIN, ACK]
从服务器 (4090) 接收并确认 (4092) 后,http 客户端尝试发送另一个 HTTP 请求,而不是立即关闭 (并可能重新建立) TCP 连接。看起来它[FIN, ACK]
只是被 HTTP 客户端忽略了。
根据 RFC 7230 (6.3),HTTP 协议规定了使用Connection
标头进行持久连接管理的最佳机制。由于客户端和服务器都支持该机制,因此该机制运行良好。
然而,HTTP 通常在 TCP 之上运行。TCP 连接管理不知道顶层协议,可以独立于 HTTP 使用。但 HTTP 客户端不支持处理此问题(可能它们不应该支持,它应该在套接字级别上得到支持)。然而,服务器确实利用了它,因为它允许优雅地关闭连接而无需发送额外的 HTTP 请求。例如,FIN
当连接超时或重新加载配置。
注意:当 HTTP 客户端RST
从服务器接收消息时,它会关闭连接。这似乎是在套接字级别完成的,因为我在 HTTP 客户端的源代码中找不到与此相关的任何内容。
- 我对情况的理解正确吗?
FIN
客户端忽略消息,而服务器使用它,似乎是完全错误的。 - 为什么
RST
是在套接字级别处理,但FIN
事实并非如此? - 是否有任何 RFC 或其他标准关于 HTTP 客户端应如何处理 TCP 连接关闭?
- 是 nginx 做了一些非标准的事情还是 HTTP 客户端不遵循标准?
PS 我能够使用 Python 2/3、Java 和httperf
用 C 编写的实用程序中的 HTTP 客户端重现它。因此,我相信 HTTP 客户端忽略消息是很常见的FIN
。我想了解原因。