linux網絡編程中阻塞和非阻塞socket的區別


原文:http://blog.sina.com.cn/s/blog_4b029ef30100nxcb.html

阻塞socket和非阻塞socket

讀操作
對於阻塞的socket,當socket的接收緩沖區中沒有數據時,read調用會一直阻塞住,直到有數據到來才返

回。當socket緩沖區中的數據量小於期望讀取的數據量時,返回實際讀取的字節數。當sockt的接收緩沖

區中的數據大於期望讀取的字節數時,讀取期望讀取的字節數,返回實際讀取的長度。

對於非阻塞socket而言,socket的接收緩沖區中有沒有數據,read調用都會立刻返回。接收緩沖區中有
數據時,與阻塞socket有數據的情況是一樣的,如果接收緩沖區中沒有數據,則返回錯誤號為

EWOULDBLOCK,
表示該操作本來應該阻塞的,但是由於本socket為非阻塞的socket,因此立刻返回,遇到這樣的情況,可

以在下次接着去嘗試讀取。如果返回值是其它負值,則表明讀取錯誤。
因此,非阻塞的rea調用一般這樣寫:

if ((nread = read(sock_fd, buffer, len)) < 0)
{
 if (errno == EWOULDBLOCK)
  {
   return 0; //表示沒有讀到數據
  }else return -1; //表示讀取失敗
}else return nread;讀到數據長度

寫操作

對於寫操作write,原理是類似的,非阻塞socket在發送緩沖區沒有空間時會直接返回錯誤號EWOULDBLOCK,
表示沒有空間可寫數據,如果錯誤號是別的值,則表明發送失敗。如果發送緩沖區中有足夠空間或者
是不足以拷貝所有待發送數據的空間的話,則拷貝前面N個能夠容納的數據,返回實際拷貝的字節數。

而對於阻塞Socket而言,如果發送緩沖區沒有空間或者空間不足的話,write操作會直接阻塞住,如果有

足夠空間,則拷貝所有數據到發送緩沖區,然后返回.
非阻塞的write操作一般寫法是:

int write_pos = 0;
int nLeft = nLen;

while (nLeft > 0)
{
 int nWrite = 0;
 if ((nWrite = write(sock_fd, data + write_pos, nLeft)) <= 0)
 {
  if (errno == EWOULDBLOCK)
                  {
   nWrite = 0;
    }else return -1; //表示寫失敗
 }
 nLeft -= nWrite;
        write_pos += nWrite;
}
return nLen;

建立連接
   阻塞方式下,connect首先發送SYN請求道服務器,當客戶端收到服務器返回的SYN的確認時,則

connect
返回.否則的話一直阻塞.
   非阻塞方式,connect將啟用TCP協議的三次握手,但是connect函數並不等待連接建立好才返回,而是
立即返回。返回的錯誤碼為EINPROGRESS,表示正在進行某種過程.

接收連接
對於阻塞方式的傾聽socket,accept在連接隊列中沒有建立好的連接時將阻塞,直到有可用的連接,才返

回。
非阻塞傾聽socket,在有沒有連接時都立即返回,沒有連接時,返回的錯誤碼為EWOULDBLOCK,表示本來應
該阻塞。


無阻塞的設置方法

方法一:fcntl
int flag;
if (flag = fcntl(fd, F_GETFL, 0) <0) perror("get flag");
flag |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, flag) < 0)
perror("set flag");

方法二:ioctl

int b_on = 1;
ioctl (fd, FIONBIO, &b_on);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM