TCP:recv() 获取 ECONNRESET

Posted

技术标签:

【中文标题】TCP:recv() 获取 ECONNRESET【英文标题】:TCP : recv() getting ECONNRESET 【发布时间】:2016-01-29 20:02:33 【问题描述】:

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

在服务器端(使用非阻塞读取):

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 吗?

【问题讨论】:

tcpdump 会告诉你实际发生了什么 【参考方案1】:

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

对端故意重置连接 对等端关闭了连接,而他仍有未读数据待处理 您已将数据发送到已被对等方关闭的连接 您有待处理的写入数据并且 TCP 重试已超时 TCP keepalive 检测到连接丢失。

这是一个致命错误,当你得到它时应该关闭套接字。

每个客户端可以随时close()shutdown() 套接字。

不,他不能。见上文。

【讨论】:

我想知道为什么recv man 中没有提到这个严重的致命错误 @susdu 官方 X/Open 文档 pubs.opengroup.org/onlinepubs/9699919799/toc.htm> 中提到了这种错误情况:如果出现以下情况,recv() 函数将失败: ... [ECONNRESET] 连接被强制关闭一个同行。 @susdu '协议层可能会产生额外的错误......'【参考方案2】:

如果远程对等点已经干净地关闭了连接,并且本地端没有更多的字节等待读取,那么是的,recv() 应该返回0。因此,如果您收到ECONNRESET,则可以合理地假设没有发生有序关闭。

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

无论如何,在ECONNRESET 之后,假设您将能够从套接字进一步读取任何内容是不合理的,因此在您的特定情况下,您可能应该像处理@987654326 一样处理它@ 返回 0,+/- 日志记录。

【讨论】:

重置可以源自您的端以及对等端。 您应该将其视为连接上的致命错误,而不是与完全断开连接。 @EJP,“你”我指的是 OP,因为他描述了他的特定程序,而不是通用的“你”。我已经澄清了。【参考方案3】:

如果客户端关闭他的身边而不读取发送的数据,你可能会得到 ECONNRESET。如果他正确关闭连接,您将获得 0。

【讨论】:

在那种情况下得到它,但还有其他的。

以上是关于TCP:recv() 获取 ECONNRESET的主要内容,如果未能解决你的问题,请参考以下文章

TCP服务器/客户端:客户端recv()返回空白缓冲区

linux epoll socket recv 不能获取正确的数据

在 Windows 中获取 Recv-Q/Send-Q?

TCP 之 TCP_NEW_SYN_RECV状态

在 C 中处理来自 recv() TCP 的部分返回

TCP socket函数recv()阻塞程序