我正在使用一个服务器,该服务器在调用recv()后返回-1并将errno设置为ECONNRESET时崩溃。我最初使用nmap找到了这个条件(我不是一个破解者,只是测试当时端口是否打开。)但是,nmap使用原始套接字所以我不太乐意将此作为测试用例提交给开发人员。我宁愿在C中编写一个可以导致ECONNRESET的客户端程序。
到目前为止,我已经尝试了两件事:connect()从我的客户端连接到服务器,然后在连接后立即关闭()套接字。服务器上的recv()仍然返回1(我已经插入了调试代码,所以我可以看到返回值。)我也尝试用一些字符串调用send(),然后立即调用shutdown()。没有骰子,绳子被传送好了。
那我怎么会造成这种情况呢?非便携式很好,我正在使用Linux。
答案 0 :(得分:5)
问题在于您正在呼叫shutdown
。请改为呼叫close
。
查看TCP状态图。
http://tangentsoft.net/wskfaq/articles/debugging-tcp.html
基本上,shutdown
通过发送FIN并等待对等方完成(FIN - > ACK / FIN - > ACK - >关闭)“礼貌地”关闭套接字,此时您将调用close
一切都很好。如果您先拨打close
而不先拨打shutdown
,那就是发送RST的“不礼貌”版本 - 相当于在电话中间挂断,而无需等待其他人完成他们在说什么。
将“关闭”视为“说再见”,将“关闭”视为“挂断”。你总是要挂断电话,但你不必先说再见。
关于nmap:为开发人员提供使用nmap的测试用例是完全可以接受的。无论如何,这是nmap的主要目的之一。
答案 1 :(得分:1)
您使用shutdown()
的直觉是正确的,但是您没有正确使用它。
据推测,您正在使用shutdown()
或SHUT_WR
尝试SHUT_RDWR
。当您关闭写入方向时,您的连接端会通过FIN
通知对等方 - 表示您的身边不会再有数据。这将导致另一端的recv()
指示连接上的文件结尾,这不是您想要的。
相反,您希望仅使用SHUT_RD
关闭套接字的读取方向,并将其保持打开以进行写入。这不会立即通知对等方 - 但如果对等方在此之后发送任何数据,则您的方将使用RST
进行响应,以通知对方有些数据丢失 - 您的客户端应用程序未看到
(因此,为了确保您重置连接,您需要确保服务器将尝试向您发送内容 - 您可能需要先发送一些内容,然后执行读取关闭)。