0
点赞
收藏
分享

微信扫一扫

socket recv阻塞与非阻塞error

茗越 2022-01-31 阅读 109

recv是socket编程中最常用的函数之一,在阻塞状态的recv有时候会返回不同的值,而对于错误值也有相应的错误码,分别对应不同的状态,下面是我针对常见的几种网络状态的简单总结。
首先阻塞接收的recv有时候会返回0,这仅在对端已经关闭TCP连接时才会发生。
而当拔掉设备网线的时候,recv并不会发生变化,仍然阻塞,如果在这个拔网线阶段,socket被关掉了,后果可能就是recv永久的阻塞了。
所以一般对于阻塞的socket都会用setsockopt来设置recv超时。
当超时时间到达后,recv会返回错误,也就是-1,而此时的错误码是EAGAIN或者EWOULDBLOCK,POSIX.1-2001上允许两个任意一个出现都行,所以建议在判断错误码上两个都写上。
如果socket是被对方用linger为0的形式关掉,也就是直接发RST的方式关闭的时候,recv也会返回错误,错误码是ENOENT
还有一种经常在代码中常见的错误码,那就是EINTER,意思是系统在接收的时候因为收到其他中断信号而被迫返回,不算socket故障,应该继续接收。但是这种情况非常难再现,但是总是会有概率出现的,所以作为完善的程序必须对此错误进行特殊处理。
一般设置超时的阻塞recv常用的方法都如下:

int foo(SOCKET socket, char *buff, int length)
{
    int nleft, nread;
    nleft = length;
    while(nleft > 0)
    {
        nread = recv(socket, buff, nleft,0);        
        if(nread == 0)//对端socket调用close()关闭
        {
            printf("%s", strerror(errno));
            return -1;
        }
        if(nread < 0)
        {
            if(errno == EINTR ||errno == EAGAIN ||errno == EWOULDBLOCK)
                continue;
            printf("%s", strerror(errno));
            return -1;
        }
        nleft -= nread;
        buff += nread;
    }
    return(length - nleft);
}

最后,如果recv的返回值为0,那表明连接已经断开,我们的接收操作也应该结束。
阻塞与非阻塞recv返回值没有区分,都是 <0 出错 =0 连接关闭 >0 接收到数据大小。

举报

相关推荐

0 条评论