我在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_onoff
,l_linger
)的两个成员的值都是零。
有什么想法吗?
答案 0 :(得分:3)
尝试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(),系统处理 呼叫的方式允许 调用线程继续快速 尽可能。这个选项需要一个 徘徊结构,如中所定义 标题,指定 选择的状态和逗留 间隔。