我正在编写一个使用C ++编写的套接字的跨平台客户端应用程序。 我有问题,当服务器完成发送给我的信息时,正在套接字上进行严格的closures。
我一直在阅读关于这个主题的其他post,我没有那么在意这个方法的权利或错误,但似乎服务器要么明确地设置SO_LINGER = 0,或者这是系统的默认行为不知道,这是一个Linux的框)。
我可以看到(在Wireshark中),数据是在毫秒内由RST发送给我的,表明服务器很难closures。 我个人不同意这种方法,因为它应该由客户端来closures套接字。
服务器团队正在说这种方法没什么问题(做一个closures而不是closures),在服务器上通常是避免累积TIMED_WAIT套接字。 在Windows上,我的select()
返回指示有东西可读(虽然我还没有读过任何“传输”数据)。
但是,由于RST的快速到达,在Windows上, recv()
返回-1,我看到错误代码10054(由对等方重置连接)。 如果我至less可以获取已发送的数据,这不会太糟糕,但似乎一旦我的客户端的套接字栈看到RST,就不会再有任何未读的字节提供给我了。
在Linux(客户端)上,没有问题。 看起来TCP栈的行为稍有不同,因为我可以在RST被授予之前读取未完成的字节。 我无法说服服务器人员他们有一个错误,因为它适用于Linux客户端。
首先,我是对的吗? 这是一个服务器端的问题? 我看不出客户端做了什么错事,所以一定是对的?
似乎服务器团队坚持要执行closures,他们不希望有TIMED_WAIT,所以我要推动他们添加一个SO_LINGER,比如2秒? 这听起来像它会解决我的问题? 据我所知,这将停止发送数据后,服务器发送一个RST,并应该给我一个机会来读取未完成的字节。
找到了我自己的问题的明确答案:
“…在接收到RST段时,接收方将立即中止连接,这个说法的意义比只意味着你不能从这个连接接收或者发送更多数据的意义更大, 这也意味着仍然在TCP接收缓冲区中的任何未读数据将会丢失 ……“引用了”TCP / IP网际互联卷II“一书。 我没有这本书,所以我只能听取他的意见。 似乎没有放弃Linux上的数据,只有Windows …
Olivier Langlois的博客
摆弄SO_LINGER强制重置的副作用是所有未完成的数据都将丢失。 事实上,你没有收到它是你需要的证明,服务器团队是错误的做到这一点。
在下面引用的RFC 793中说'这个命令[ABORT]导致所有挂起的SEND和RECEIVE被中断,…和一个特殊的RESET消息被发送到连接另一端的TCP。 另见WR Stevens, TCP / IP Illustrated, Vol。 1,p。 287:“中止连接为应用程序提供了两个功能:(1)任何排队的数据被丢弃,并立即发送重置,(2)RST的接收者可以知道另一端是中止而不是正常关闭“。 有类似的措词,以及实施它的BSD代码摘录, 2。
TIME_WAIT状态只发生在接收到FIN之前发送FIN的套接字:请参阅RFC 793 。 所以服务器应该等待来自客户端的一个FIN,并有合适的超时时间,而不是重置。 这也将允许客户端进行连接池。