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值

 

 

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