【问题标题】:What happens when a server closes the connection and the client sends some data at the same time?当服务器关闭连接并且客户端同时发送一些数据时会发生什么?
【发布时间】:2021-11-20 07:06:38
【问题描述】:

我有一个用C 编写的服务器,如果连接在特定时间处于空闲状态,它会关闭连接。我有一个问题(很少发生)。客户端读取失败,显示Connection broken。我怀疑服务器正在关闭连接,而客户端正在同时发送一些数据。

考虑以下场景(A 是服务器,B 是客户端)

  1. B 发起连接,AB 之间的连接建立。
  2. B 处于空闲状态,已达到空闲超时。
  3. A 发起关闭
  4. B收到来自AFIN之前,它开始向A发送请求
  5. B发送请求后,会读取响应

由于A 已经关闭连接,B 无法读取。

我的问题是

  1. 这是一种可能的情况吗?
  2. 如何处理客户端的空闲超时?
  3. 如何正确关闭AB之间的连接(过程中避免B发送请求)。简而言之,如何原子地关闭连接?

【问题讨论】:

  • 你不应该使用代码格式来强调,代码格式用于代码。而是使用粗体或斜体,就像在 MS Word 中写信一样。
  • 1.是的。 2. 如果超时时间为 5 秒,客户端不应允许消息之间超过一秒。如果客户端没有要发送的内容,并且已经过了一秒钟,那么它应该只发送一条保持活动消息,即没有内容的消息。根据需要调整超时值,但与保活率相比,超时应该足够大。 3. 在关闭连接之前(由于超时),服务器应该向客户端发送“检测到超时”消息。
  • 我不能同意服务器发送超时消息的所有建议。此时,服务器必须假设连接已断开,并且可能断开,并且无论如何超时消息可能永远不会到达客户端,或者客户端可能无法正确响应:如果服务器然后关闭连接,客户端仍然可以得到broken pipe。你只需要忍受broken pipe 消息。所有超时消息和响应所做的只是为broken pipe 添加更多机会。

标签: c linux sockets network-programming


【解决方案1】:

根据我的基本网络经验...假设您谈论的是面向连接的连接,例如 TCP/IP,而不是无连接的 UDP/IP。

  1. 是的,当然。你无法避免它。

  2. 有多种方法可以做到这一点,但它们都包括: 在服务器超时之前从客户端发送一些东西。如果客户端没有数据要发送,让它发送类似“生命标志”的东西。这可能是一条空数据消息,这完全取决于您的应用程序协议。或者根据需要延长超时时间,包括一些余量。某些协议仅在允许的空闲时间的 3 倍后才超时。

  3. 您不能自动关闭连接,因为客户端和服务器是分开的。网络上的每个数据包都需要一些时间来传输,并且两者都可以同时开始发送,服务器端发送关闭消息,客户端发送新数据消息。对此您无能为力。

    您需要让客户端正确处理这种情况。例如,它可以接受这种断开的连接并将其解释为已关闭。如果服务器在客户端空闲时关闭连接,您应该已经有所反应。

【讨论】:

    【解决方案2】:

    如何正确关闭A和B之间的连接(过程中避免B发送请求)。

    • 服务器检测到超时
    • 服务器向客户端发送超时检测消息
    • 服务器等待回复(如果超时,假设客户端已死)
    • 如果客户端从服务器接收到超时检测,它会回复ACK(或类似的东西)
    • 如果服务器收到来自客户端的ACK,则“优雅地”关闭连接
    • 从现在开始,服务器和客户端都不应发送/接收任何消息(发送ACK后,不要立即关闭来自客户端的连接,请等待约定的超时时间 -请参阅 setsockopt: SO_LINGER)

    最重要的是,与建议的其他答案一样,客户端应在空闲时发送 heartbeat(以避免超时检测)。

    【讨论】:

    • 这也是一个很好的解决方案,但不包括因其他原因导致连接中断的情况。客户端仍然需要处理发送错误。
    • @thebusybee 我不认为这是这里的问题。当然,必须正确处理传输错误是对的,但据我了解 OP,问题不是在发生错误时出现,而是在正常情况下出现,顺便说一句。可以ans会发生。我认为适当的握手将是解决方案。
    • 所有这一切都只是复制 TCP/IP 已经做的事情。如果服务器超时读取客户端的超时响应会发生什么?没有优势。
    • @user207421 来自send 的联机帮助页:在 send() 中没有隐含发送失败的指示。返回值 -1 表示本地检测到的错误。 这对 OP 的问题有何帮助? OP 正在寻找这种保证。
    • OP 不能有这个保证,正是你所说的原因。不能保证您的超时消息比其他任何内容都传递,并且服务器无法判断它是否已传递。
    猜你喜欢
    • 1970-01-01
    • 2018-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多