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 |
有數據 | 返回數據的大小(不超過指定的讀入大小) | 返回數據的大小(不超過指定的讀入大小) |