TCP:recv()得到ECONNRESET

问题描述:

我想在Linux上使用TCP 和标准的socket.h库实现一个简单的客户端/服务器程序。服务器处理多个客户端,每个客户端可以随时关闭()或关闭()套接字。TCP:recv()得到ECONNRESET

在服务器端

(使用非阻塞读):

int nBytes; 
if ((nBytes = recv(socket, buffer, BUFFER_SIZE, MSG_DONTWAIT)) == -1) 
{ 
    if (errno != EAGAIN && errno != EWOULDBLOCK) 
    { 
     //print to log 
    } 

} 
if (nBytes == 0) 
{ 

    //other side closed the connection 
} 

我得到的recv()返回-1和错误设置为ECONNRESET。如果客户端已经关闭连接,不应该recv()返回0?

+0

tcpdump会告诉你实际发生的情况 – pm100

有许多原因,包括但不限于:

  • 同行故意重置连接
  • 对方关闭了连接,同时他仍然有悬而未决
  • 你已经发送的数据未读数据一个已经被对等关闭的连接
  • 您有待处理的写入数据并且TCP重试已超时
  • TCP保持活动检测到连接丢失。

这是一个致命错误,您应该在收到套接字时关闭套接字。

每个客户端可以在任何时候想要close()shutdown()插槽。

不,他不能。往上看。

+0

我想知道为什么在recv中没有提到这个致命的错误 – susdu

+2

@susdu这个错误情况在:如果出现以下情况,则recv()函数将失败:... [ECONNRESET] 连接被对等方强制关闭。 –

+0

@susdu'协议层可能会生成额外的错误...' – EJP

如果客户端没有读取发送的数据,他可能会收到ECONNRESET。如果他正确地关闭了连接,你会得到0.

+0

你会在这种情况下得到它,但也有其他的。 – EJP

如果远程对等方干净地关闭了连接,并且在本地没有更多字节等待读取,那么yes,recv()应该返回0。所以,如果你得到一个ECONNRESET,那么有理由认为有序关闭不是发生了什么。

ECONNRESET通常表示远程对等体发送了一个RST数据包,而没有首先关闭连接。这可能发生的原因有很多。另外,正如EJP所观察到的,重置也可能源自本地。

在任何情况下,一个ECONNRESET后,它不是合理的假设,你将能够从插座还读什么,所以你的具体情况你应该处理它一样一样的,你处理recv()返回0方式,+/-记录。

+1

重置可以源自您的末端以及对等体。 – EJP

+0

谢谢,@EJP;答案已更新。 –

+0

您应该将其作为连接上的致命错误处理,与干净的断开连接无异。 – EJP