網絡編程 read 阻塞和非阻塞下的區別

1,read 原型,參數以及返回值。

#include <uinstd.h>

ssize_t read(int fd, void *buf, size_t nbytes);

-----read,只是將內核中緩衝區的數據搬到用戶進程空間。

參數:

fd:某個連接的套接字。

buf:從內核緩衝區讀入的數據放到用戶緩衝區的地址。

nbytes:希望讀入的數據大小,一般不是真正讀人的大小。

返回值:實際讀取的長度。

     -1:error會被置爲相應的值。

           error:爲EAGAIN,表示在非阻塞下,此時無數據到達,立即返回。

           error:爲EINTR,表示被信號中斷了。

     0:對端已關閉,本端也需要close 該套接字。

    >0:實際讀取的數據長度。

 

2,read 阻塞和非阻塞下的區別:

  • 阻塞下

        原則是在不超過指定的長度下,有多少讀多少,沒有數據則一直等待,有可能會被信號中斷。

       比如,對端write寫了10字節,本端read 讀20字節,則此時read 直接返回,不用等待數據到達20字節後再返回,返回的長度是10字節。        

  • 非阻塞

       沒有數據的話,返回-1,並置相應的error;有數據的話直接返回讀入的數據大小,不超過指定的長度。

    比如,對端write寫了10字節,本端read 只讀5字節,則此時read 端返回5字節,剩下的5字節需要下次再讀入,這種情況下需要循環讀入。

 

3,read 循環讀。

int nread(int fd, char *buf, int nbytes)
{
    int len = 0;
    int left = nbytes;
    char *ptr = buf;
    
    while(left)
    {
        len = read(fd, ptr, left);
        if(len == -1)
        {
            if(error == EAGAIN)
                len = 0;
            
        }
        if(len == 0)
        {
            close(fd);
            break;
        }
        left -= len;
        ptr += len;
    }
    return nbytes;
}

    4,爲什麼read 不能一次性讀完,需要循環來讀?

        當fd爲管道或socket時,對方數據多次發送或網絡延時較大時,一次read 都可能只讀到部分數據。(因爲tcp是面向字節流的)

5,總結

read 阻塞下 非阻塞
無數據 一直等待 立馬返回-1,error置爲EAGAIN
有數據 返回數據的大小(不超過指定的讀入大小) 返回數據的大小(不超過指定的讀入大小)

 

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