1. 程式人生 > >read,recv,readv,recvfrom,recvmsg

read,recv,readv,recvfrom,recvmsg

簡介

每一個TCP套介面有一個傳送緩衝區,可以用SO_SNDBUF套介面選項來改變這個緩衝區的大小。當應用程序呼叫 write時,核心從應用程序的緩衝區中拷貝所有資料到套介面的傳送緩衝區。如果套介面的傳送緩衝區容不下應用程式的所有資料(或是應用程序的緩衝區大於 套介面傳送緩衝區,或是套介面傳送緩衝區還有其他資料),應用程序將被掛起(睡眠)。這裡假設套介面是阻塞的,這是通常的預設設定。核心將不從write 系統呼叫返回,直到應用程序緩衝區中的所有資料都拷貝到套介面傳送緩衝區。因此從寫一個TCP套介面的write呼叫成功返回僅僅表示我們可以重新使用應 用程序的緩衝區。它並不告訴我們對端的 TCP或應用程序已經接收了資料。
    TCP取套介面傳送緩衝區的資料並把它傳送給對端TCP,其過程基於TCP資料傳輸的所有規則。對端TCP必須確認收到的資料,只有收到對端的ACK,本端TCP才能刪除套介面傳送緩衝區中已經確認的資料。TCP必須保留資料拷貝直到對端確認為止。

1.輸入操作: read、readv、recv、recvfrom、recvmsg

    如果某個程序對一個阻塞的TCP套介面呼叫這些輸入函式之一,而且該套介面的接收緩衝區中沒有資料可讀,該程序將被投入睡眠,直到到達一些資料。既然 TCP是位元組流協議,該程序的喚醒就是隻要到達一些資料:這些資料既可能是單個位元組,也可以是一個完整的TCP分節中的資料。如果想等到某個固定數目的數 據可讀為止,可以呼叫readn函式,或者指定MSG_WAITALL標誌。

    既然UDP是資料報協議,如果一個阻塞的UDP套介面的接收緩衝區為空,對它呼叫輸入函式的程序將被投入睡眠,直到到達一個UDP資料報。

    對於非阻塞的套介面,如果輸入操作不能被滿足(對於TCP套介面即至少有一個位元組的資料可讀,對於UDP套介面即有一個完整的資料報可讀),相應呼叫將立即返回一個EWOULDBLOCK錯誤。

read函式只是一個通用的讀檔案裝置的介面。是否阻塞需要由裝置的屬性和設定所決定。一般來說,讀字 符終端、網路的socket描述字,管道檔案等,這些檔案的預設read都是阻塞的方式。如果是讀磁碟上的檔案,一般不會是阻塞方式的。但使用鎖和 fcntl設定取消檔案O_NOBLOCK狀態,也會產生阻塞的read效果。

char chBuff[32];
read(file_pipe[0], chBuff, 16);

如果管道沒有資料我這個函式就永遠不返回,請問有沒有其它的方式,如果管道有資料就讀取,沒資料也立即返回 

或者在open的時候,傳入O_NONBLOCK引數,按非阻塞方式開啟 / fcntl(fd, F_SETFL, O_NONBLOCK)

在mode設定O_NONBLOCK標誌

2. 輸出操作:write、writev、send、sendto、sendmsg

    對於一個TCP套介面,核心將從應用程序的緩衝區到該套介面的傳送緩衝區拷貝資料。對於阻塞的套介面,如果其傳送緩衝區中沒有空間,程序將被投入睡眠,直到有空間為止。

    對於一個非阻塞的TCP套介面,如果其傳送緩衝區中根本沒有空間,輸出函式呼叫將立即返回一個EWOULDBLOCK錯誤。如果其傳送緩衝區中有一些空間,返回值將是核心能夠拷貝到該緩衝區中的位元組數。這個位元組數也稱為不足計數(short count)

    UDP套介面不才能在真正的傳送緩衝區。核心只是拷貝應用程序資料並把它沿協議棧向下傳送,漸次冠以UDP頭部和IP頭部。因此對一個阻塞的UDP套介面,輸出函式呼叫將不會因為與TCP套介面一樣的原因而阻塞,不過有可能會因其他的原因而阻塞