recv函数和send函数返回值错误处理

本文中分析的都是非阻塞态的socket错误代码,因为阻塞态也不会出现EWOULDBLOCK错误。

1、recv函数:

返回值<0时并且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的,继续接收。

socket设置为非阻塞的时候,recv返回错误时才会有 errno == EWOULDBLOCK || errno == EAGAIN两种情况;

  • #define EWOULDBLOCK    EAGAIN 

          因为宏定义EWOULDBLOCK和 EAGAIN ,所以二者等价;

  • EWOULDBLOCK,WOULD英文语法是表示过去将来式,表示本来应该。。。;

        放在此处的意思是,本来应该阻塞,却没有阻塞。(也就是并没有发生阻塞,原因是设置了非阻塞态,也就说这个错误是在非阻塞态时才会有的)

EWOULDBLOCK的意思是如果你不把socket设成非阻塞(即阻塞)模式时,这个读操作将阻塞,也就是说数据还未准备好(但系统知道数据来了,所以select告诉你那个socket可读)。使用非阻塞模式做I/O操作的细心的人会检查errno是不是EAGAIN、EWOULDBLOCK、EINTR,如果是就应该重读,一般是用循环。如果你不是一定要用非阻塞就不要设成这样,这就是为什么系统的默认模式是阻塞。

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函数是不能通过返回值来判断读满了buff个数据的,因为recv返回0表示,对端socket正常关闭了。

所以,需要通过判断未读的字节数>0?来解决这个问题。

2、send函数

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

 

3、附录

recv函数errno值

send函数errno值

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章