1.sock預設為阻塞模式,下面的**可對sock設定為非阻塞模式
int flags = fcntl(sock, f_getfl, 0);
fcntl(sock, f_setfl, flags | o_nonblock);
假設當前**為伺服器,並且已經執行過如下**,
當sock為阻塞模式,呼叫accept會阻塞直到乙個請求到來
當sock為非阻塞模式,accept會返回-1,errno設定為eagain或者ewouldblock
static int ns_open_listening_socket_tcp()
else if (sock != -1)
return sock;
}
3,對於sock_stream 套接字,應用程式意識不到報文邊界,因為套接字提供的是位元組流服務,因此當從套接字讀出資料時,它也許不會返回所有由傳送程序所寫的位元組,最終獲取所有資料,也許要通過若干次函式呼叫得到
sock為阻塞和非阻塞對recv是沒有影響的,
recv在accept沒有建立新的sock之前,都是立即返回-1,並且errno 為 9,
#define ebadf 9 /* bad file number */
在accept建立好連線以後,沒有資料接收之前都會一直阻塞,
若有資料接收,recv則返回值》0;
若無資料接收,recv阻塞;
若對方斷開連線,則recv返回值為0;
那麼有錯誤處理函式:
當recv返回0時,套接字關閉,出錯close退出
當recv返回負數,並且不為以下幾種情況時,出錯退出:
#define eintr 4 /* interrupted system call */
#define einprogress 115 /* operation now in progress */
#define eagain 11 /* try again */
#define ewouldblock eagain /* operation would block */
static int ns_is_error(int n)
recv函式
int recv( socket s, char far *buf, int len, int flags);
不論是客戶還是伺服器應用程式都用recv函式從tcp連線的另一端接收資料。
該函式的第乙個引數指定接收端套接字描述符;
第二個引數指明乙個緩衝區,該緩衝區用來存放recv函式接收到的資料;
第三個引數指明buf的長度; 第四個引數一般置0。
這裡只描述同步socket的recv函式的執行流程。當應用程式呼叫recv函式時,
(1)recv先等待s的傳送緩衝中的資料被協議傳送完畢,如果協議在傳送s的傳送緩衝中的資料時出現網路錯誤,那麼recv函式返回socket_error,
(2)如果s的傳送緩衝中沒有資料或者資料被協議成功傳送完畢後,recv先檢查套接字s的接收緩衝區,
如果s接收緩衝區中沒有資料或者協議正在接收數 據,那麼recv就一直等待,直到協議把資料接收完畢。
當協議把資料接收完畢,recv函式就把s的接收緩衝中的資料copy到buf中
(注意協議接收到的資料可能大於buf的長度,所以 在這種情況下要呼叫幾次recv函式才能把s的接收緩衝中的資料copy完。
recv函式僅僅是copy資料,真正的接收資料是協議來完成的), recv函式返回其實際copy的位元組數。
如果recv在copy時出錯,那麼它返回socket_error;
如果recv函式在等待協議接收資料時網路中斷了,那麼它返回0。
預設 socket 是阻塞的 解阻塞與非阻塞recv返回值沒有區分,都是<0 出錯 =0 連線關閉 >0 接收到資料大小,
特別:返回值<0時並且(errno == eintr || errno == ewouldblock || errno == eagain)的情況下認為連線是正常的,繼續接收。
只是阻塞模式下recv會阻塞著接收資料,非阻塞模式下如果沒有資料會返回,不會阻塞著讀,因此需要迴圈讀取)。
返回說明:
成功執行時,返回接收到的位元組數。
另一端已關閉則返回0。
失敗返回-1,
errno被設為以下的某個值
eagain:套接字已標記為非阻塞,而接收操作被阻塞或者接收超時
ebadf:sock不是有效的描述詞
econnrefuse:遠端主機阻絕網路連線
efault:記憶體空間訪問出錯
eintr:操作被訊號中斷
einval:引數無效
enomem:記憶體不足
enotconn:與面向連線關聯的套接字尚未被連線上
enotsock:sock索引的不是套接字 當返回值是0時,為正常關閉連線;
思考:當對側沒有send,即本側的套接字s的接收緩衝區無資料,返回值是什麼(eagain,原因為超時,待測)
測試**:
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //offsetof
#include static int ns_is_error(int n)
static void ns_set_non_blocking_mode(int sock)
static int ns_open_listening_socket_tcp()
else if (sock != -1)
return sock;
}void main()
sleep(1);
} }
若要接收大檔案,則當客戶端斷開後,n為0 ,才會斷開連線,認為一次接收完畢。
若recv返回了,但沒有出錯,則不會關閉newsock,在下一輪中繼續接收
**如下:
void main()
; char out[10240];
int sock = ns_open_listening_socket_tcp();
newsock = -1;
while(1)
if(newsock>=0)
strcat(out,buf);
memset(buf,0,sizeof(buf));
} if(ns_is_error(n))
}}
若把accept以後的newsock設定為非阻塞,則為以下模式:設定newsock的超時時間,當recv超時後,返回,返回的n為-1,errno為11,這個時候,仍然不會認為出錯,等待下一次接收。void main()
; char out[10240];
int sock = ns_open_listening_socket_tcp();
// int timeout=1;
struct timeval timeout = ;
newsock = -1;
while(1)
if(newsock>0)
printf("n:%d,errno:%d\n",n,errno);
if(ns_is_error(n))
} }
}
綜上,recv只有返回0時,才結束傳輸。
ns_is_error(n)為真 時,才關閉socket(真的結束了,即n==0,或者出錯了)
為假時,不用關閉socket下一輪繼續接收。
TCP Socket程式設計(非阻塞模式)(C )
伺服器 tcpserver.cpp 定義控制台應用程式的入口點。include stdafx.h include include pragma comment lib,ws2 32.lib define buf size 64 int tmain int argc,tchar argv 建立用於監聽...
阻塞與非阻塞賦值
李秋鳳,華清遠見嵌入式學院 講師。稍微接觸過verilog hdl的都對阻塞與非阻塞賦值略知一二,也是我們經常強調的重點之一,在課堂上還是有學員問什麼不一樣呢,為什麼我用阻塞賦值也能得出正確的結果呢?在編寫可綜合 的時候,建議大家不要忘了開啟rtl網表檢視器看看我們自己綜合出來的電路是不是自己想要的...
socket connect 阻塞與非阻塞
socket函式生成socket結構體時,預設生成的socket是阻塞的 如果我們使用connect去連線伺服器,而這時網路出現故障,則connect預設等候很長一段時間然後返回錯誤 我們可以設定socket為非阻塞模式,可以設定一定的等候時間,如果在設定的等候時間內connect失敗,則我們判定網...