導航:首頁 > 編程系統 > linuxsocket阻塞模式

linuxsocket阻塞模式

發布時間:2023-01-18 05:45:27

linux下socket的阻塞模式有什麼用

等待被連接

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

阻塞的是意思是這樣:read函數讀的時候,如果此時數據包沒有來,那就程序就會暫停執行,在read函數裡面暫停。它如何繼續執行呢?那就是數據包來之後它繼續執行。非阻塞就是說,如何執行read函數的時候,數據包沒有,那麼read函數返回沒有讀到任何東西,如果執行read函數時候恰好有數據包,那麼read函數將返回讀到的數據包。也就是說,阻塞的socket使用read的時候,你都能保證讀到數據包。而非阻塞就不一定了,所以往往非阻塞需要配合循環,不停的讀,或者設置一個超時。如果讀了幾次,或者等待了多少秒沒有讀到,就超時。阻塞的,無法控制時間。

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

用一個函數舉例吧,比如伺服器端在等待客戶端接入的時候,是調用accept函數,如果是阻塞的情況下,程序會一直停在accept函數這里,一直判斷有沒有客戶端接入。而如果是非阻塞的情況下,程序只會在當前的時間上調用accept函數,只判斷一次有沒有客戶端接入,不管有沒有,判斷完後程序就會接著執行下面的代碼。(如果想用非阻塞,就在accept函數前調用select函數吧)

㈣ 同步與非同步,阻塞與非阻塞的區別,以及select,poll和epoll

非同步的概念和同步相對。
(1)當一個同步調用發出後,調用者要一直等待返回消息(結果)通知後,才能進行後續的執行;

(2)當一個非同步過程調用發出後,調用者不能立刻得到返回消息(結果)。實際處理這個調用的部件在完成後,通過 狀態、通知和回調 來通知調用者。

這里提到執行部件和調用者通過三種途徑返回結果:狀態、通知和回調。使用哪一種通知機制,依賴於執行部件的實現,除非執行部件提供多種選擇,否則不受調用者控制。

(A)阻塞調用是指調用結果返回之前,當前線程會被掛起,一直處於等待消息通知,不能夠執行其他業務

(B)非阻塞調用是指在不能立刻得到結果之前,該函數不會阻塞當前線程,而會立刻返回

場景比喻:
舉個例子,比如我去銀行辦理業務,可能會有兩種方式:

在上面的場景中,如果:
a)如果選擇排隊(同步),且排隊的時候什麼都不幹(線程被掛起,什麼都幹不了),是同步阻塞模型;
b)如果選擇排隊(同步),但是排隊的同時做與辦銀行業務無關的事情,比如抽煙,(線程沒有被掛起,還可以干一些其他的事),是同步非阻塞模型;
c)如果選擇拿個小票,做在位置上等著叫號(通知),但是坐在位置上什麼都不幹(線程被掛起,什麼都幹不了),這是非同步阻塞模型;
d)如果選擇那個小票,坐在位置上等著叫號(通知),但是坐著的同時還打電話談生意(線程沒有被掛起,還可以干其他事情),這是非同步非阻塞模型。

對這四種模型做一個總結:
1:同步阻塞模型,效率最低,即你專心排隊,什麼都不幹。
2:非同步阻塞,效率也非常低,即你拿著號等著被叫(通知),但是坐那什麼都不幹
3:同步非阻塞,效率其實也不高,因為涉及到線程的來回切換。即你在排隊的同時打電話或者抽煙,但是你必須時不時得在隊伍中挪動。程序需要在排隊和打電話這兩種動作之間來回切換,系統開銷可想而知。
4:非同步非阻塞,效率很高,你拿著小票在那坐著等叫號(通知)的同時,打電話談你的生意。

linux下幾個基本概念
1:用戶控制項和內核空間。 現代操作系統都是採用虛擬存儲器,在32位操作系統下,它的定址空間(虛擬存儲空間)為4G(2的32次方)。為了保證用戶進程補鞥呢直接操作內核,保證內核的安全,操作系統將虛擬空間劃分為兩部分,一部分為內核空間,一部分為用戶空間。對linux操作系統而言,將最高的1G位元組空間分給了內核使用,稱為內核空間,將較低的3G位元組的空間劃分為用戶空間。

2:進程切換很耗資源 ,為了控制進程的執行,內核必須有能力掛起正在cpu上運行的進程,並恢復以前掛起的某個進程的執行,這種行為叫進程的切換。每次切換,要保存上一個的上下文環境等等,總之記住進程切換很耗資源。

3:文件描述符 :文件描述符在形式上是一個非負整數。實際上,他是一個索引,指向內核為每個進程所維護的該進程打開文件的記錄表。當程序打開一個文件時,內核就會向進程返回一個非負整數的文件描述符。但是文件描述符一般在unix,linux系統中才講。

緩存IO ,大多數系統的默認IO操作都是緩存IO,在linux的緩存IO機制中,操作系統會將IO的數據緩存在系統的頁緩存(page cache)中,也就是說,數據會先被拷貝到操作系統內核的緩沖區,然後才會從操作系統內核的緩沖區拷貝到應用程序的地址空間。 緩存IO的缺點: 數據在傳輸過程中需要在應用程序和地址空間和內核進行多次數據拷貝操作,這種數據拷貝操作鎖帶來的cpu以及內存消耗是很大的。

LINUX的IO模型
網路IO的本質是socket的讀取。socket在linux系統被抽象為流,故對網路IO的操作可以理解為對流的操作。

對於一次IO訪問,比如以read操作為例, 數據會先被拷貝到操作系統內核的緩沖區,然後才會從內核緩沖區拷貝到進程的用戶層,即應用程序的地址空間 。故當一個read操作發生時,其實是經歷了兩個階段:
1:內核緩沖區的數據就位
2:數據從內核緩沖區拷貝到用戶程序地址空間

那麼具體到socket io的一次read操來說,這兩步分別是:
1:等待網路上的數據分組到達,然後復制到內核緩沖區中
2:數據從內核緩沖區拷貝到用戶程序的地址空間(緩沖區)

所以說 網路應用要處理的無非就兩個問題:網路IO和數據計算 ,一般來說網路io帶來的延遲影響比較大。

網路IO的模型大致有如下幾種:

熟悉不? 我們常說的select,poll和epoll就是屬於同步模型中多路復用IO的不同實現方法罷了。 下面分別對同步阻塞,同步不阻塞,同步io復用進行說明。

一:同步阻塞
它是最簡單也最常用的網路IO模型。linux下默認的socket都是blocking的。

從圖中可以看到,用戶進程調用recvfrom這個系統調用後,就處於阻塞狀態。然後kernel就開始了IO的第一個階段:數據准備。等第一個階段准備完成之後,kernel開始第二階段,將數據從內核緩沖區拷貝到用戶程序緩沖區(需要花費一定時間)。然後kernel返回結果(確切的說是recvfrom這個系統調用函數返回結果),用戶進程才結束blocking,重新運行起來。
總結 同步阻塞模型下,用戶程序在kernel執行io的兩個階段都被blocking住了 。但是優點也是因為這個,無延遲能及時返回數據,且程序模型簡單。

二:同步非阻塞
同步非阻塞就是隔一會瞄一下的輪詢方式。同步非阻塞模式其實是可以看做一小段一小段的同步阻塞模式。

三:IO多路復用
由於同步非阻塞方式需要不斷的輪詢,光輪詢就占據了很大一部分過程,且消耗cpu資源。而這個用戶進程可能不止對這個socket的read,可能還有對其他socket的read或者write操作,那人們就想到了一次輪詢的時候,不光只查詢詢一個socket fd,而是在一次輪詢下,查詢多個任務的socket fd的完成狀態,只要有任何一個任務完成,就去處理它。而且,輪詢人不是進程的用戶態,而是有人幫忙就好了。那麼這就是所謂的 IO多路復用 。總所周知的linux下的select,poll和epoll就是這么乾的。。。

selelct調用是內核級別的,selelct輪詢相比較同步非阻塞模式下的輪詢的區別為: 前者可以等待多個socket,能實現同時對多個IO埠的監聽 ,當其中任何一個socket數據准備好了,就返回可讀。 select或poll調用之後,會阻塞進程 ,與blocking IO 阻塞不用在於,此時的select不是等到所有socket數據達到再處理,而是某個socket數據就會返回給用戶進程來處理。
其實select這種相比較同步non-blocking的效果在單個任務的情況下可能還更差一些 ,因為這里調用了select和recvfrom兩個system call,而non-blocking只調用了一個recvfrom,但是 用select的優勢在於它可以同時處理多個socket fd

在io復用模型下,對於每一個socket,一般都設置成non-blocking,但是其實 整個用戶進程是一直被block的 ,只不過用戶process不是被socket IO給block住,而是被select這個函數block住的。

與多進程多線程技術相比,IO多路復用的最大優勢是系統開銷小。

一:select
select函數監視多個socket fs,直到有描述符就緒或者超時,函數返回。當select函數返回後,可以通過遍歷fdset,來找到就緒的描述符。select的基本流程為:

二:poll
poll本質上跟select沒有區別,它將用戶傳入的數組拷貝到內核空間,然後查詢每個fd的狀態,如果某個fd的狀態為就緒,則將此fd加入到等待隊列中並繼續遍歷。如果遍歷完所有的fd後發現沒有就緒的,則掛起當前進程,直到設備就緒或者主動超時。被喚醒後它又要再次遍歷fd。
特點:
1:poll沒有最大連接數限制,因為它是用基於鏈表來存儲的,跟selelct直接監聽fd不一樣。
2:同樣的大量的fd的數組被整體復制與用戶態和內核地址空間之間。
3:poll還有一個特點是水平觸發:如果報告了fd後沒有被處理,則下次poll時還會再次報告該fd。
4:跟select一樣,在poll返回後,還是需要通過遍歷fdset來獲取已經就緒的socket。當fd很多時,效率會線性下降。

三:epoll

epoll支持水平觸發和邊緣觸發,最大的特點在於邊緣觸發,它只告訴進程哪些fd剛剛變為就緒態,並且只會通知一次。還有一個特點是,epoll使用「事件」的就緒通知方式,通過epoll_ctl注冊fd,一旦該fd就緒,內核就會採用類似callback的回調機制來激活該fd,epoll_wait便可以收到通知。

沒有最大並發連接的限制,能打開的FD的上限遠大於1024(1G的內存上能監聽約10萬個埠)。

效率提升,不是輪詢的方式,不會隨著FD數目的增加效率下降。只有活躍可用的FD才會調用callback函數;即Epoll最大的優點就在於它只管你「活躍」的連接,而跟連接總數無關,因此在實際的網路環境中,Epoll的效率就會遠遠高於select和poll。

內存拷貝,利用mmap()文件映射內存加速與內核空間的消息傳遞;即epoll使用mmap減少復制開銷。

聊聊同步、非同步、阻塞與非阻塞
聊聊Linux 五種IO模型
聊聊IO多路復用之select、poll、epoll詳解

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

很好區別:
阻塞式:在用read()函數讀取網路中的數據流的數據的時候,如果讀不到數據,這個函數就會一直阻塞,不會返回,你的進程也停留在這一步,知道有客戶端向你發送數據,read()函數讀到數據了,然後程序就接著網下走。

非阻塞式:在用read()函數讀取網路中的數據流的數據的時候,不管有沒有數據都會返回,且程序繼續往下執行。

㈥ socket通信可不可以Server端設成非阻塞方式,Client端設成阻塞模式

Windows用socket設置非阻塞式 :

unsigned long ul=1;

SOCKET s=socket(AF_INET,SOCK_STREAM,0);

int ret=ioctlsocket(s, FIONBIO, (unsigned long *)&ul);//設置非阻塞模式

if(ret==SOCKET_ERROR)//設置失敗

{

}

Linux用socket設置非阻塞式

int flags = fcntl(socket, F_GETFL, 0);

fcntl(socket, F_SETFL, flags | O_NONBLOCK);

用socket設置非阻塞式

int flags = fcntl(socket, F_GETFL, 0);

fcntl(socket, F_SETFL, flags | O_NONBLOCK);

非阻塞設置阻塞用

int flags = fcntl(socket, F_GETFL, 0);

fcntl(socket, F_SETFL, flags & ~O_NONBLOCK);

功能描述:根據文件描述詞操作文件特性

用:

int fcntl(int fd, int cmd);

int fcntl(int fd, int cmd, long arg);

int fcntl(int fd, int cmd, struct flock *lock);

參數:

fd:文件描述詞

cmd:操作命令

arg:供命令使用參數

lock:同

操作命令供使用

. F_DUPFD :復制文件描述詞

二. FD_CLOEXEC :設置close-on-exec標志FD_CLOEXEC位0執行execve程文件保持打反則關閉

三. F_GETFD :讀取文件描述詞標志

四. F_SETFD :設置文件描述詞標志

五. F_GETFL :讀取文件狀態標志

六. F_SETFL :設置文件狀態標志

其O_RDONLY O_WRONLY O_RDWR O_CREAT O_EXCL O_NOCTTY O_TRUNC受影響

更改標志 O_APPENDO_ASYNC O_DIRECT O_NOATIME O_NONBLOCK

七. F_GETLK, F_SETLK F_SETLKW :獲取釋放或測試記錄鎖使用參數結構體指針:

F_SETLK:指定位元組范圍獲取鎖(F_RDLCK, F_WRLCK)或者釋放鎖(F_UNLCK)與另進程鎖操作發沖突返 -1並errno設置EACCES或EAGAIN

F_SETLKW:行同F_SETLK除能獲取鎖睡眠等待外等待程接收信號立即返並errno置EINTR

F_GETLK:獲取文件鎖信息

F_UNLCK:釋放文件鎖

設置讀鎖文件必須讀式打設置寫鎖文件必須寫式打設置讀寫鎖文件必須讀寫式打

㈦ linux網路編程中阻塞和非阻塞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);

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

阻塞:一般的I/O操作可以在新建的流中運用.在伺服器回應前它等待客戶端發送一個空白的行.當會話結束時,伺服器關閉流和客戶端socket.如果在隊列中沒有請示將會出現什麼情況呢?那個方法將會等待一個的到來.這個行為叫阻塞.accept()方法將會阻塞伺服器線程直到一個呼叫到來.當5個連接處理完閉之後,伺服器退出.任何的在隊列中的呼叫將會被取消.
非阻塞:非阻塞套接字是指執行此套接字的網路調用時,不管是否執行成功,都立即返回。比如調用recv()函數讀取網路緩沖區中數據,不管是否讀到數據都立即返回,而不會一直掛在此函數調用上。在實際Windows網路通信軟體開發中,非同步非阻塞套接字是用的最多的。平常所說的C/S(客戶端/伺服器)結構的軟體就是非同步非阻塞模式的

㈨ linux socket阻塞recv怎麼返回

recv是socket編程中最常用的函數之一,在阻塞狀態的recv有時候會返回不同的值,而對於錯誤值也有相應的錯誤碼,分別對應不同的狀態,下面是我針對常見的幾種網路狀態的簡單總結。
首先阻塞接收的recv有時候會返回0,這僅在對端已經關閉TCP連接時才會發生。
而當拔掉設備網線的時候,recv並不會發生變化,仍然阻塞,如果在這個拔網線階段,socket被關掉了,後果可能就是recv永久的阻塞了。
所以一般對於阻塞的socket都會用setsockopt來設置recv超時。
當超時時間到達後,recv會返回錯誤,也就是-1,而此時的錯誤碼是EAGAIN或者EWOULDBLOCK,POSIX.1-2001上允許兩個任意一個出現都行,所以建議在判斷錯誤碼上兩個都寫上。
如果socket是被對方用linger為0的形式關掉,也就是直接發RST的方式關閉的時候,recv也會返回錯誤,錯誤碼是ENOENT
還有一種經常在代碼中常見的錯誤碼,那就是EINTER,意思是系統在接收的時候因為收到其他中斷信號而被迫返回,不算socket故障,應該繼續接收。但是這種情況非常難再現,我嘗試過一邊一直在不停的發信號,一邊用recv接收數據,也沒有出現過。這種異常錯誤我附近只有一個朋友在用write的時候見到過一次,但是總是會有概率出現的,所以作為完善的程序必須對此錯誤進行特殊處理。
一般設置超時的阻塞recv常用的方法都如下:
while(1)
{
cnt = (int)recv(m_socket, pBuf,RECVSIZE, 0);
if( cnt >0 )
{
//正常處理數據
}
else
{
if((cnt<0) &&(errno == EAGAIN||errno == EWOULDBLOCK||errno == EINTR)) //這幾種錯誤碼,認為連接是正常的,繼續接收
{
continue;//繼續接收數據
}
break;//跳出接收循環
}
}
阻塞與非阻塞recv返回值沒有區分,都是 <0 出錯 =0 連接關閉 >0 接收到數據大小。

Linux環境下,須如下定義:struct timeval timeout = {3,0};
//設置發送超時
setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval));
//設置接收超時
setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));

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

阻塞
阻塞調用是指調用結果返回之前,當前線程會被掛起(線程進入非可執行狀態,在這個狀態下,cpu不會給線程分配時間片,即線程暫停運行)。函數只有在得到結果之後才會返回。

非阻塞
非阻塞和阻塞的概念相對應,指在不能立刻得到結果之前,該函數不會阻塞當前線程,而會立刻返回。

閱讀全文

與linuxsocket阻塞模式相關的資料

熱點內容
表示文件路徑用什麼字元隔開 瀏覽:549
word2010宏安全性設置 瀏覽:820
win7硬碟密碼設置 瀏覽:240
電腦有沒有這個文件在哪裡查 瀏覽:340
金蘋果內容摘要 瀏覽:580
網站怎麼對接qq在線客服 瀏覽:437
solidworks曲面建模教程 瀏覽:69
數控編程和計算機有什麼區別 瀏覽:541
jsp與webservice 瀏覽:659
k歌的數據包括什麼 瀏覽:300
寬頻wifi怎麼查看網站 瀏覽:97
vlog網頁編程怎麼樣 瀏覽:598
自助下單網站多少錢搭建 瀏覽:130
國外裝修都用什麼app 瀏覽:326
qq同步助手修改密碼 瀏覽:850
電腦與電腦傳輸文件 瀏覽:403
處理網路數據應用哪個好 瀏覽:229
萬靈召喚最新版本 瀏覽:566
電腦文件夾自動備份 瀏覽:380
御史大冒險怎麼升級快 瀏覽:284

友情鏈接