没有SO_LINGER> 0的强制服务器端套接字关闭会丢失数据,对吧?

use*_*763 5 c++ sockets linux windows

我正在编写一个使用C++编写的套接字的跨平台客户端应用程序.我遇到问题,当服务器发送信息时,服务器正在对套接字进行严格关闭.

我一直在阅读关于这个主题的其他帖子,我对这种方法的权利或错误并不是那么感兴趣,但似乎服务器要么显式设置SO_LINGER = 0,要么就是该系统的默认行为(不确定,这是一个Linux盒子).

我可以看到(在Wireshark中)发送给我的数据是在毫秒内由RST发送的,表明服务器已经关闭了.我个人不同意这种方法,因为应该由客户端来关闭套接字.

服务器团队表示这种方法没有任何问题(进行硬关闭而不是关闭),在服务器上通常会避免累积TIMED_WAIT套接字.在Windows上我的select()返回表明有东西要读(虽然我还没有读过任何这个"传输中"的数据).

但是,由于RST的快速到达,在Windows上recv()返回-1并且我看到错误代码为10054(由对等方重置连接).如果我至少可以获取已发送的数据,这不会太糟糕,但似乎一旦我的客户端的套接字堆栈看到RST,任何未读的字节都不再可用.

在Linux(客户端)上,没有问题.似乎TCP堆栈的行为略有不同,因为我可以在RST被尊重之前读取未完成的字节.鉴于它适用于Linux客户端,我无法说服服务器人他们有错误.

首先,我是对的吗?这是服务器端问题吗?我看不出客户端做错了什么,所以一定是对的?

似乎服务器团队坚持要求他们执行关闭,并且他们不想拥有TIMED_WAIT,所以我要推动他们添加SO_LINGER,比如说2秒?这听起来会解决我的问题吗?根据我的理解,这将阻止服务器在发送数据后立即发送RST,并且应该让我有机会读取未完成的字节.

use*_*421 2

摆弄 SO_LINGER 来强制重置的副作用是所有挂起的数据都会丢失。您没有收到它的事实就足以证明服务器团队这样做是错误的。

下面引用的 RFC 793 说“此命令 [ABORT] 导致所有挂起的 SEND 和 RECEIVE 被中止,...并且一个特殊的 RESET 消息将发送到连接另一端的 TCP。” 另请参见 WR Stevens,《TCP/IP 插图》,第 1 卷。1,p。287:'中止连接为应用程序提供了两个功能:(1)任何排队的数据都被丢弃并立即发送重置,(2)RST的接收者可以知道另一端执行了中止而不是正常关闭。第 1 卷中有类似的措辞,以及实现它的 BSD 代码的摘录。2.

TIME_WAIT 状态仅发生在在收到 FIN 之前发送 FIN 的套接字上:请参阅RFC 793。因此服务器应该等待客户端的 FIN,并设置适当的超时时间,而不是重置。这也将允许客户端进行连接池。