【问题标题】:"Connection Reset by Peer" if server calls close() immediately after write()如果服务器在 write() 之后立即调用 close(),则“由 Peer 重置连接”
【发布时间】:2011-09-08 08:52:20
【问题描述】:

我有一个用 C 语言编写的 AF_INET/SOCK_STREAM 服务器,在 Android/Linux 上运行,看起来更像这样:

...
for (;;) {
    client = accept(...);
    read(client, &message, sizeof(message));
    response = process(&message);
    write(client, response, sizeof(*response));
    close(client);
}

据我所知,关闭调用不应立即终止与客户端的连接,但它显然会:客户端在有机会读取服务器响应之前报告“对等连接重置”。

如果我在 write()close() 之间插入延迟,客户端可以按预期读取响应。

我得到一个提示,它可能与 SO_LINGER 选项有关,但我检查了它的值,并且 struct linger 的两个成员(l_onoffl_linger)的值都为零。

有什么想法吗?

【问题讨论】:

    标签: c linux sockets posix android-ndk


    【解决方案1】:

    Stevens 描述了一种可能发生这种情况的配置,但这取决于客户端在服务器调用 close() 之后发送更多数据(在客户端应该“知道”连接正在关闭之后)。 UNP 第 2 版 s5.12。

    尝试 tcpdumping 对话以了解实际情况。如果有可能在两个端点之间存在“智能”网关(例如 NAT),则 tcpdump 两端并查找差异。

    【讨论】:

    • 我怀疑这是正在发生的事情。 +1 以抓住这种可能性并就如何调试这种情况提供好的建议。
    【解决方案2】:

    如果您希望在关闭生效之前发送排队数据,则应设置 SO_LINGER(即设置为 1 而不是 0)。

    SO_LINGER 如果数据存在,则停留在 close() 上。该选项控制 未发送消息时采取的措施 套接字上的队列和 close() 是 执行。如果设置了 SO_LINGER,则 系统将阻塞调用线程 在 close() 期间,直到它可以传输 数据或直到时间到期。如果 SO_LINGER 未指定,并且 close() 发出,系统处理 通话的方式允许 调用线程以尽快继续 尽可能。这个选项需要一个 逗留结构,如定义 标头,指定 期权的状态和徘徊 间隔。

    【讨论】:

    • 这不应该影响客户端/网络,只是让服务器在逗留期间阻塞而不是继续。
    【解决方案3】:

    当您在发送数据的连接上调用close() 时,连接会重置。特别针对这种情况,使用带有 SHUT_WR 标志的shutdown() 序列,然后使用阻塞read()

    关闭套接字的写端发送FIN并立即返回,一旦你的对等方及时回复FIN,所述read()阻塞并返回0。基本上,这就是您所需要的代替您所说的write()close() 之间的延迟。

    在这种情况下,您不需要对 linger 选项执行任何操作,将其全部保留为默认值。

    【讨论】:

      猜你喜欢
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-01
      • 2017-07-24
      • 2012-02-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多