我正在尝试使用TCP和标准的socket.h库在linux上实现一个简单的客户端/服务器程序 . 服务器处理多个客户端,每个客户端可以随时关闭()或关闭()套接字 .
在服务器端(使用非阻塞读取):
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?
3 回答
原因很多,包括但不限于:
对等方故意重置连接
对等方关闭了连接,而他仍然有待处理的未读数据
您已将数据发送到已由对等方关闭的连接
您有待处理的写入数据,并且TCP重试已超时
TCP keepalive检测到连接丢失 .
这是致命错误,您应该在获得它时关闭套接字 .
不,他不能 . 往上看 .
如果远程对等方已完全关闭连接,并且本地端没有更多字节等待读取,则是,
recv()
应返回0
. 因此,如果你得到一个ECONNRESET
那么可以合理地假设有序关闭不是发生的事情 .ECONNRESET
经常表示远程对等方发送了RST数据包而没有先干净地关闭连接 . 造成这种情况的原因有很多 . 或者,正如EJP观察到的那样,重置也可能在本地产生 .在任何情况下,在
ECONNRESET
之后,假设您将能够从套接字中进一步读取任何内容是不合理的,因此在您的特定情况下,您可能应该像处理recv()
返回0
,/ - 记录一样处理它 .如果客户端在没有读取发送数据的情况下关闭他的一方,您可能会获得ECONNRESET如果他正确地关闭连接你就会得到0 .