如何从客户端在recv()中导致ECONNRESET?

时间:2011-05-04 06:43:40

标签: c linux sockets posix

我正在使用一个服务器,该服务器在调用recv()后返回-1并将errno设置为ECONNRESET时崩溃。我最初使用nmap找到了这个条件(我不是一个破解者,只是测试当时端口是否打开。)但是,nmap使用原始套接字所以我不太乐意将此作为测试用例提交给开发人员。我宁愿在C中编写一个可以导致ECONNRESET的客户端程序。

到目前为止,我已经尝试了两件事:connect()从我的客户端连接到服务器,然后在连接后立即关闭()套接字。服务器上的recv()仍然返回1(我已经插入了调试代码,所以我可以看到返回值。)我也尝试用一些字符串调用send(),然后立即调用shutdown()。没有骰子,绳子被传送好了。

那我怎么会造成这种情况呢?非便携式很好,我正在使用Linux。

2 个答案:

答案 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进行响应,以通知对方有些数据丢失 - 您的客户端应用程序未看到

(因此,为了确保您重置连接,您需要确保服务器将尝试向您发送内容 - 您可能需要先发送一些内容,然后执行读取关闭)。