int send( SOCKET s, const char FAR *buf, int len, int flags );
不論是客戶還是服務器應用程序都用send函數來向TCP連接的另一端發送數據。客戶程序一般用send函數向服務器發送請求,而服務器則通常用send函數來向客戶程序發送應答。
該函數的第一個參數指定發送端套接字描述符(發給誰寫誰的socket);
第二個參數指明一個存放應用程序要發送數據的緩沖區;
第三個參數指明實際要發送的數據的字節數;
第四個參數一般置0。
這里只描述同步Socket的send函數的執行流程。當調用該函數時,
(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中的數據copy到剩余空間里(注意并不是send把s的發送緩沖中的數據傳到連接的另一端的,而是協議傳的,send僅僅是把buf中的數據copy到s的發送緩沖區的剩余空間里)。
如果send函數copy數據成功,就返回實際copy的字節數,如果send在copy數據時出現錯誤,那么send就返回SOCKET_ERROR;如果send在等待協議傳送數據時網絡斷開的話,那么send函數也返回SOCKET_ERROR。
要注意send函數把buf中的數據成功copy到s的發送緩沖的剩余空間里后它就返回了,但是此時這些數據并不一定馬上被傳到連接的另一端。如 果協議在后續的傳送過程中出現網絡錯誤的話,那么下一個Socket函數就會返回SOCKET_ERROR。(每一個除send外的Socket函數在執 行的最開始總要先等待套接字的發送緩沖中的數據被協議傳送完畢才能繼續,如果在等待時出現網絡錯誤,那么該Socket函數就返回 SOCKET_ERROR)
注意:在Unix系統下,如果send在等待協議傳送數據時網絡斷開的話,調用send的進程會接收到一個SIGPipE信號,進程對該信號的默認處理是進程終止。
通過測試發現,異步socket的send函數在網絡剛剛斷開時還能發送返回相應的字節數,同時使用select檢測也是可寫的,但是過幾秒鐘之后,再send就會出錯了,返回-1。select也不能檢測出可寫了。
2. 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數據,真正的接收數據是協議來完成的),
首先要理解的是,緩沖區有兩種。第一種是用戶定義的緩沖區,就是send里的緩沖區參數。另一種就是套接字緩沖區,是由協議自定的。可以用getsockopt獲取其大小,并用setsockopt重置其大小。發送的時候使用send實際上是從用戶緩沖區發送到socket緩沖區中,至于數據真正何時發送給另一端則是由協議規定的。Recv也類似。
獲取方法:
int reuse;
int nlen;getsockopt(sd,SOL_SOCKET,SO_SNDBUF,( char *)&reuse,&nlen);
看了這段話之后,我使用Windsock先獲取了socket緩沖區為8192,但是直接發送10000的數據也不會阻塞,在我的機器上發送23684時候阻塞,在別的機器上是不同的值,不知道內部是如何實現的。但是如果不斷發送同時另一端也在接受,且用戶定義的接受緩沖區的大小大于8192的話,在之后的發送過程中會每次填充8192;如果另一端用戶定義接受緩沖區小于8192,如1000則發送端就會分開發送,如3752一次,4440一次,并且之后都是這樣,加起來也是8192,就是不明白windsock的send的內部實現機制了。
頂0踩新聞熱點
疑難解答