【问题标题】:What could cause a socket to close quickly after every HTTP transaction?什么会导致套接字在每次 HTTP 事务后快速关闭?
【发布时间】:2012-04-05 12:09:52
【问题描述】:

我有一个 Delphi 6 应用程序,它与充当 HTTP 服务器的外部设备通信。我正在为此应用程序使用 ICS TWSocket 组件。我打开一个套接字与设备通信,并处理必要的标头和正文制作以与服务器通信。换句话说,我没有使用 ICS HTTP 客户端组件,而是使用较低级别的 TWSocket 组件并自己处理必要的 HTTP“握手”。

我制作并发送到外部设备的标头将保持活动标志设置为 TRUE。在我的系统上,在我向外部设备发送任何内容后,连接将持续保持打开状态并且不会关闭,直到发生大约 30 秒的非活动状态(30 秒我没有向外部设备发出任何请求作为 HTTP 服务器) .我不知道外部设备是否关闭了它,或者 Microsoft Windows 是否关闭了它。但重要的一点是,通常我可以进行多次发送,并且连接将保持打开状态,直到我在大约 30 秒内什么都不发送。这工作正常,是我的代码所期望的。

但是,在我的一些用户系统上,套接字在每次发送后都会关闭。我确实有代码检查关闭的套接字并在必要时尝试重新连接到外部设备,但不希望每次事务都必须重新连接。

我的问题是:

  • 是否存在可能导致某些用户系统出现这种异常行为的套接字系统设置?

  • 如果是这样,我是否可以使用 Windows API 函数调用来查询有问题的参数,然后将其设置为预期在 30 秒不活动时关闭,而不是在每次交易时关闭?

  • 如果是这样,我能否或如何以不会对用户系统上运行的任何其他程序产生不利影响的方式执行此操作?

【问题讨论】:

  • 外部设备总是相同的版本,使用相同的配置,并且没有通过某种代理连接?因为看起来差异是由不同的服务器或中间的东西引起的。
  • 这可能只是在该特定设备上运行的 HTTP/1.0。 1.0 版没有持久连接。无论如何,wireshark 是你的朋友。
  • 首先,请使用微软网络监视器或Wireshark查看连接是如何关闭的(哪一方发送TCP RESET),然后您可以开始进一步分析。

标签: delphi http sockets keep-alive


【解决方案1】:

服务器正在关闭套接字。这有三个可能的原因:

  • 客户端发出 HTTP/1.0 请求
  • 客户端在请求中设置了Connection: close标头
  • 服务器不支持持久连接

HTTP/1.0 不支持持久连接,服务器在 HTTP/1.0 请求后关闭套接字是正确的。

HTTP/1.1 指定连接是隐式持久的,除非客户端指定Connection: close 标头。如果服务器收到此标头,则关闭连接是正确的。如果服务器不支持持久连接,关闭连接也是正确的。

如果您使用的是 HTTP/1.1,则可以通过发送 Connection: keep-alive 标头来强制连接保持持久(只要服务器支持)。然后您还应该发送一个Keep-Alive: timeout=<secs>, max=<max-requests> 标头,其中<secs><max-requests> 是代表所需行为的整数。

【讨论】:

  • 对于 HTTP 1.0,客户端可以发送 Connection: keep-alive 请求标头来请求持久连接。大多数 HTTP 1.0 服务器都支持它作为非官方扩展,因为在 HTTP 1.0 中默认不启用 keep-alive。服务器的Connection 响应标头将指示保持活动是否被兑现。
  • @DaveRandom - 请在下面查看我的评论并感谢 Remy。
  • @RemyLebeau(和 Dave) - 根据响应标头,服务器似乎是 HTTP 1.0:“HTTP/1.0 200 OK”+“服务器:WYM/1.0”。我总是有“连接:保持活动”行,但只是在我的请求中添加了“保持活动超时=30 max=3”行。服务器在响应标头中返回以下行,状态为 200 OK:“Connection: Keep-Alive” + “Keep-Alive: timeout=3600, max=108000”。尽管有 HTTP 1.0 支持,这是否(必然)表明成功?但是,我检查了用户的调试日志,这两条 keep-alive 行确实已经从服务器返回。
  • @RobertOschler:响应的版本不能比请求的版本更新。如果请求是 HTTP 1.0,则响应将是 HTTP 1.0,即使服务器支持更新的 HTTP 版本。如果响应返回 Connection: keep-alive 标头,则连接在服务器端是持久的,因此客户端可以重用连接来发送下一个请求。如果客户端等待的时间过长,并且在发送下一个请求之前已经过了keep-alive超时,则服务器将关闭连接并且发送将失败,在这种情况下,客户端可以简单地重新连接并发送。
  • @RemyLebeau - re:请求版本。我指出了这一点,因为在我尝试将请求更改为 HTTP 1.1 之后,我仍然从服务器返回了 HTTP 1.0。所以我仍然不知道为什么套接字正在关闭,因为尽管服务器支持 HTTP 1.0 并返回正确的 Keep-Alive 行来指示它,但它看起来像这样,套接字在每次事务后关闭。我会尝试让用户运行 WireShark 或类似工具,以查看谁正在关闭连接。
猜你喜欢
  • 2019-08-15
  • 1970-01-01
  • 2017-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 2019-09-10
  • 1970-01-01
相关资源
最近更新 更多