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

时间:2012-11-24 16:33:45

标签: c++ linux windows sockets

我正在编写一个使用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,并且应该让我有机会读取未完成的字节。

2 个答案:

答案 0 :(得分:1)

摆弄SO_LINGER以强制重置的副作用是所有待处理数据都会丢失。你没有收到它的事实就是服务器团队做错的所有证据。

下面引用的RFC 793表示'此命令[ABORT]导致所有待处理的SEND和RECEIVE中止,...以及要在连接另一端发送到TCP的特殊RESET消息。 #39;另见W.R. Stevens, TCP / IP Illustrated, Vol。 1,p。 287:'中止连接为应用程序提供了两个功能:(1)丢弃任何排队的数据并立即发送重置,以及(2)RST的接收者可以告诉另一端执行了中止而不是正常的关闭'在Vol。中有类似的措辞,以及实现它的BSD代码的摘录。 2。

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

答案 1 :(得分:1)

找到了我自己问题的明确答案:

“...收到RST段后,接收方将立即中止连接。此声明具有更多含义,而不仅仅意味着您将无法从此连接接收或发送任何更多数据。< strong>它还暗示仍然在TCP接收缓冲区中的任何未读数据都将丢失 ......“它引用了”TCP / IP Internetworking Volume II“一书。我没有那本书,所以我只能接受他的话。似乎没有丢弃Linux上的数据,只有Windows ...

Olivier Langlois's blog