阻塞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);
㈡ 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函數詳細解釋下吧
函數原型:int socket(int family,int type,int protocol); 參數解釋:family指定協議簇,UNIX下(包括linux)有:AF_INET,AF_INET6,AF_LOCAL,AF_ROUTE,AF_KEY,分別是IPv4,IPv6協議,UNIX域協議,路由套介面,密鑰套介面; type指定套介面類型:unix下有四種,分別是:SOCK_STREAM,SOCK_DGRAM,SOCK_SEQPACKET,SOCK_RAW。(流套接字,數據報套接字,有序分組套接字,原始套接字),SOCK_SEQPACKET已很少使用; protocol:IPPROTO_TCP,IPPROTO_UDP,IPPROTO_SCTP,分別是TCP傳輸協議,UDP傳輸協議,SCTP傳輸協議; 函數返回一個非負整數值,類似於文件描述符(linux內核知識),稱之為套介面描述字,簡稱套接字。《Linux就該這么學》這本書,希望你能感受到linux系統和這本書帶給你的好處及幫助。
㈣ linux 網路編程socket問題:
如果在本地測試的話肯定是可以的。因為在1000毫秒裡面,數據早已經傳完了。而我們看到的時間18時12分12秒只是假象。
但是如果server端和client端隔離的比較遠,例如區域網這么近的地方,就未必能夠在相同的時間接收到數據。
㈤ linux網路編程中阻塞和非阻塞socket的區別
阻塞:一般的I/O操作可以在新建的流中運用.在伺服器回應前它等待客戶端發送一個空白的行.當會話結束時,伺服器關閉流和客戶端socket.如果在隊列中沒有請示將會出現什麼情況呢?那個方法將會等待一個的到來.這個行為叫阻塞.accept()方法將會阻塞伺服器線程直到一個呼叫到來.當5個連接處理完閉之後,伺服器退出.任何的在隊列中的呼叫將會被取消.
非阻塞:非阻塞套接字是指執行此套接字的網路調用時,不管是否執行成功,都立即返回。比如調用recv()函數讀取網路緩沖區中數據,不管是否讀到數據都立即返回,而不會一直掛在此函數調用上。在實際Windows網路通信軟體開發中,非同步非阻塞套接字是用的最多的。平常所說的C/S(客戶端/伺服器)結構的軟體就是非同步非阻塞模式的
㈥ linux socket網路編程怎樣收發包
1.send函數
ssize_t send( SOCKET s, const char *buf, size_t len, int flags );
(1)send先比較待發送數據的長度len和套接字s的發送緩沖的長度, 如果len大於s的發送緩沖區的長度,該函數返回SOCKET_ERROR;
(2)如果len小於或者等於s的發送緩沖區的長度,那麼send先檢查協議是否正在發送s的發送緩沖中的數據,如果是就等待協議把數據發送完,如果協議還沒有開始發送s的發送緩沖中的數據或者s的發送緩沖中沒有數據,那麼send就比較s的發送緩沖區的剩餘空間和len;
(3)如果len大於剩餘空間大小,send就一直等待協議把s的發送緩沖中的數據發送完;
(4)如果len小於剩餘空間大小,send就僅僅把buf中的數據到剩餘空間里(注意並不是send把s的發送緩沖中的數據傳到連接的另一端的,而是協議傳送的,send僅僅是把buf中的數據到s的發送緩沖區的剩餘空間里)。
注意:
(1)如果send函數數據成功,就返回實際的位元組數,如果send在數據時出現錯誤,那麼send就返回SOCKET_ERROR;如果send在等待協議傳送數據時網路斷開的話,那麼send函數也返回SOCKET_ERROR。
(2)要注意send函數把buf中的數據成功到s的發送緩沖的剩餘空間里後它就返回了,但是此時這些數據並不一定馬上被傳到連接的另一端。如果協議在後續的傳送過程中出現網路錯誤的話,那麼下一個Socket函數就會返回SOCKET_ERROR。(每一個除send外的Socket函數在執行的最開始總要先等待套接字的發送緩沖中的數據被協議傳送完畢才能繼續,如果在等待時出現網路錯誤,那麼該Socket函數就返回 SOCKET_ERROR)
(3)在Unix系統下,如果send在等待協議傳送數據時網路斷開的話,調用send的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。
2.recv函數
ssize_t recv(int s, char *buf, size_t len, int flags);
(1)recv先等待s的發送緩沖中的數據被協議傳送完畢,如果協議在傳送s的發送緩沖
中的數據時出現網路錯誤,那麼recv函數返回SOCKET_ERROR。
(2)如果s的發送緩沖中沒有數據或者數據被協議成功發送完畢後,recv先檢查套接字s的接收緩沖區,如果s接收緩沖區中沒有數據或者協議正在接收數 據,那麼recv就一直等待,直到協議把數據接收完畢。當協議把數據接收完畢,recv函數就把s的接收緩沖中的數據到buf中。(注意:協議接收到的數據可能大於buf的長度,所以 在這種情況下要調用幾次recv函數才能把s的接收緩沖中的數據完。recv函數僅僅是數據,真正的接收數據是協議來完成的)
(3)recv函數返回其實際的位元組數。如果recv在時出錯,那麼它返回SOCKET_ERROR;如果recv函數在等待協議接收數據時網路中斷了,那麼它返回0。
注意:在Unix系統下,如果recv函數在等待協議接收數據時網路斷開了,那麼調用recv的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。
Q&A:
(1)兩次send一次recv會發生什麼?
一次性讀取兩次send的內容。
(2)recv之後,接收緩沖區會被清空嗎?
是的。
㈦ 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;讀到數據長度
㈧ linux網路編程中阻塞和非阻塞socket的區別
阻塞的是意思是這樣:read函數讀的時候,如果此時數據包沒有來,那就程序就會暫停執行,在read函數裡面暫停。它如何繼續執行呢?那就是數據包來之後它繼續執行。非阻塞就是說,如何執行read函數的時候,數據包沒有,那麼read函數返回沒有讀到任何東西,如果執行read函數時候恰好有數據包,那麼read函數將返回讀到的數據包。也就是說,阻塞的socket使用read的時候,你都能保證讀到數據包。而非阻塞就不一定了,所以往往非阻塞需要配合循環,不停的讀,或者設置一個超時。如果讀了幾次,或者等待了多少秒沒有讀到,就超時。阻塞的,無法控制時間。