如果服务器在write()之后立即调用close(),则“Peer连接重置”

时间:2011-06-04 12:37:44

标签: c linux sockets posix android-ndk

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

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

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

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

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

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

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

尝试tcpdumping对话,找出真正发生的事情。如果两个端点之间存在“聪明”网关(例如NAT)的可能性,则tcpdump会结束并查找差异。

答案 1 :(得分:1)

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

关闭套接字的写入端会发送FIN并立即返回,并且所述read()会阻止并在对等方以适当的方式回复FIN时返回0。基本上,这就是您所需要的,而不是您所谈论的write()close()之间的延迟。

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

答案 2 :(得分:0)

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

  

SO_LINGER       如果存在数据,则关闭close()。此选项控制   未发送消息时采取的行动   socket上的队列和close()是   执行。如果设置了SO_LINGER,则   系统应阻止调用线程   在close()期间直到它可以传输   数据或直到时间到期。如果   未指定SO_LINGER,并且   发出close(),系统处理   呼叫的方式允许   调用线程继续快速   尽可能。这个选项需要一个   徘徊结构,如中所定义    标题,指定   选择的状态和逗留   间隔。