實驗8 非阻塞I O

2021-09-21 16:52:01 字數 3688 閱讀 5222

i/o

1 阻塞socket 

和非阻塞

socket

設定乙個套接字為非阻塞模式,相當於通知核心當乙個套接字相關的

i/o 

操作不能立刻

完成的時候,不要將呼叫者設為休眠狀態,而是應該返回乙個錯誤**。其區別如下圖所示:

核心應用

read, recvfrom(write,sendto,accept,connect)

wait for data come in

copy data

copy completely

return

continue to process with data

核心應用

read

return ewouldblock immediately

read

return ewouldblock immediately

read

拷貝資料到使用者空間

return success

處理資料

1.1 

讀操作 對於阻塞的

socket,

當socket  

的接收緩衝區中沒有資料時,

read 

呼叫會一直阻塞住,直

到有資料到來才返回。當

socket 

緩衝區中的資料量小於期望讀取的資料量時,返回實際讀

sockt 

的接收緩衝區中的資料大於期望讀取的位元組數時,讀取期望讀取的字

節數,返回實際讀取的長度。

對於非阻塞

socket 

而言,socket 

的接收緩衝區中有沒有資料,

read 

呼叫都會立刻返回。

接收緩衝區中有資料時,與阻塞

socket 

有資料的情況是一樣的,如果接收緩衝區中沒有數

據,則返回錯誤號為

ewouldblock,

表示該操作本來應該阻塞的,但是由於本

socket 

為非阻塞的

socket

,因此立刻返回,遇

到這樣的情況,可以在下次接著去嘗試讀取。如果返回值是其它負值,則表明讀取錯誤。

因此,非阻塞的

read 

呼叫一般這樣寫:

if ((nread  = read(sock_fd, buffer, len)) < 0)

else return -1; //

表示讀取失敗

}else return  nread;

讀到資料長度

1.2 

寫操作 對於寫操作

write,

原理是類似的,非阻塞

socket  

在傳送緩衝區沒有空間時會直接返回錯

誤號ewouldblock,

表示沒有空間可寫資料,如果錯誤號是別的值,則表明傳送失敗。

如果傳送緩衝區中有足夠空間或者是不足以拷貝所有待傳送資料的空間的話,則拷貝前面

n 個能夠容納的資料,返回實際拷貝的位元組數。

而對於阻塞

socket 

而言,如果傳送緩衝區沒有空間或者空間不足的話,

write 

操作會直

接阻塞住,如果有足夠空間,則拷貝所有資料到傳送緩衝區,然後返回。

非阻塞的

write 

操作一般寫法是

: int write_pos = 0;

int  nleft = nlen;

while (nleft > 0)

nleft -= nwrite;

write_pos += nwrite;

} return nwrite

1.3 

建立連線

阻塞方式下,

connect 

首先傳送

syn 

請求道伺服器,當客戶端收到伺服器返回的

syn 

的 確認時,則

connect 

返回。否則的話一直阻塞。

非阻塞方式,

connect 

將啟用tcp 

協議的三次握手,但是

connect 

函式並不等待連線建立

好才返回,而是立即返回。返回的錯誤碼為

einprogress,

表示正在進行某種過程。接收

socket,accept 

在連線佇列中沒有建立好的連線時將阻塞,直到有可

用的連線,才返回。

非阻塞傾

聽socket, 在有

沒有連線時都

立即返回,沒

有連線時,返

回的錯誤碼

為 ewouldblock,

表示本來應該阻塞。

2 無阻塞的設定方法

方法一:fcntl

int flag=fcntl(fd, f_getfl, 0);

fcntl(fd, f_setfl, flag|o_nonblock) ;

方法二:ioctl

int b_on = 1;

ioctl (fd, fionbio, &b_on);

3 程式分析:

下面的程式利用非阻塞模式下的

conncet 

函式,進行埠掃瞄。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

//使用方法:

scan 192.168.1.1  192.168.2.10 89 500

int main(int argc, char* ar**) ;

if(argc==1)

if(argc==5)

if(startip==inaddr_none||endip==inaddr_none) ;

if(startport==0||endport==0)

; long i,j;

for(i=ntohl(startip);i<=ntohl(endip);i++)

/*由於是非阻塞工作模式,因此對於來不及返回0 的

connect 

函式, errno 

應該為einprogress

,表示正在建立這個連線*/

fd_set wset;

fd_zero(&wset);

fd_set(fd,&wset);

struct timeval timeout;

timeout.tv_sec=0;

timeout.tv_usec=10000;//10 

毫秒 int rs=select(fd+1,null,&wset,null,&timeout);//

等待10 

毫秒,等待

這個fd 

是否可寫,可寫表示已經建立了連線

int error=0;

int len=sizeof error;

if((rs==1)&&(getsockopt(fd,sol_socket,so_error,&error,&len)==0))

close(fd);

continue;

} }}

阻塞I O,非阻塞I O

拿 socket舉例。當read資料時,如果這時沒有資料可讀,阻塞i o會一直等待有資料讀,資料從kernel copy 到socket的buffer後返回 非阻塞i o會立即返回,但如果有資料可讀,非阻塞i o也是等資料從kernel copy 到socket的buffer後返回。以上是阻塞與非阻...

第8章 阻塞與非阻塞I O

阻塞操作 在執行裝置操作時,若不能獲得資源,則掛起程序直到滿足可操作的條件後再進行操作。被掛起的程序進入睡眠狀態,被從排程器的執行佇列移走,直到等待條件被滿足。非阻塞操作 在不能進行裝置操作時,並不掛起,要麼放棄要麼不停地查詢,直至可以進行操作為止。喚醒程序的地方最大可能發生在中斷裡面,因為在硬體資...

非阻塞IO和阻塞IO

非阻塞io和阻塞io 在網路程式設計中對於乙個網路控制代碼會遇到阻塞io 和非阻塞io 的概念,這裡對於這兩種socket 先做一下說明 基本概念 阻塞io socket 的阻塞模式意味著必須要做完io 操作 包括錯誤 才會返回。非阻塞io 非阻塞模式下無論操作是否完成都會立刻返回,需要通過其他方式...