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的主要内容,如果未能解决你的问题,请参考以下文章