send 和recv详解
int send( SOCKET s,??????const char FAR *buf,??????int len,??????int flags );??
不論是客戶還是服務器應用程序都用send函數來向TCP連接的另一端發送數據。
客戶程序一般用send函數向服務器發送請求,而服務器則通常用send函數來向客戶程序發送應答。
該函數的第一個參數指定發送端套接字描述符;
第二個參數指明一個存放應用程序要發送數據的緩沖區;
第三個參數指明實際要發送的數據的字節數;
第四個參數一般置0。
這里只描述同步Socket的send函數的執行流程。當調用該函數時,send先比較待發送數據的長度len和套接字s的發送緩沖的長度,
如果len大于s的發送緩沖區的長度,該函數返回SOCKET_ERROR;如果len小于或者等于s的發送緩沖區的長度,那么send先檢查協議
是否正在發送s的發送緩沖中的數據,如果是就等待協議把數據發送完,如果協議還沒有開始發送s的發送緩沖中的數據或者s的發送
緩沖中沒有數據,那么 send就比較s的發送緩沖區的剩余空間和len,如果len大于剩余空間大小send就一直等待協議把s的發送緩沖
中的數據發送完,如果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也不能檢測出可寫了。
recv函數
int recv( SOCKET s,?????char FAR *buf,??????int len,?????int flags?????);??
不論是客戶還是服務器應用程序都用recv函數從TCP連接的另一端接收數據。
該函數的第一個參數指定接收端套接字描述符;
第二個參數指明一個緩沖區,該緩沖區用來存放recv函數接收到的數據;
第三個參數指明buf的長度;
第四個參數一般置0。
這里只描述同步Socket的recv函數的執行流程。當應用程序調用recv函數時,recv先等待s的發送緩沖中的數據被協議傳送完畢,
如果協議在傳送s的發送緩沖中的數據時出現網絡錯誤,那么recv函數返回SOCKET_ERROR,如果s的發送緩沖中沒有數據或者數據
被協議成功發送完畢后,recv先檢查套接字s的接收緩沖區,如果s接收緩沖區中沒有數據或者協議正在接收數據,那么recv就一直
等待,直到協議把數據接收完畢。當協議把數據接收完畢,recv函數就把s的接收緩沖中的數據copy到buf中(注意協議接收到的數據
可能大于buf的長度,所以在這種情況下要調用幾次recv函數才能把s的接收緩沖中的數據copy完。recv函數僅僅是copy數據,真正的
接收數據是協議來完成的),recv函數返回其實際copy的字節數。如果recv在copy時出錯,那么它返回SOCKET_ERROR;如果recv函數在等待協議接收數據時網絡中斷了,那么它返回0。
注意:在Unix系統下,如果recv函數在等待協議接收數據時網絡斷開了,那么調用recv的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。
int send (
???SOCKET s,?????????????
???const char FAR * buf,?
???int len,??????????????
???int flags?????????????
);
請問send函數每次最多可以發送多少數據?是int的最大值嗎?
【sms88】:
不是int的最大值
【sms88】:
理論上似乎是一個窗口大小減去協議頭的大小
【xxyyboy】:
不是, send???有不指定長度的,有指定長度的。
int send (
???SOCKET s,?????????????????//鏈路
???const char FAR * buf,?????//buffer 內容
???int len,???????????????????//buffer len
???int flags?????????????????//不知道
);
函數 int 只是表示發送成功失敗的返回值,不表示 多長
像你這個就是 有buffer 就發送
recv到的數據流可能是斷斷續續的,你要把他們放在一起然后解碼。
【dodoboy】:
那也就是說如果buffer中的數據過大,我也只需要調用一次send函數,而低層到底是一次傳輸成功還是陸續傳輸我不用管了嗎?
【mudunke775】:
recv到的數據流可能是斷斷續續的,你要把他們放在一起然后解碼。
//
解碼和合并包是低層做的,不用你自己解碼吧?
【unsigned】:
Send分為阻塞和非阻塞,阻塞模式下,如果正常的話,會直到把你所需要發送的數據發完再返回;非阻塞,會根據你的socket在底層的
可用緩沖區的大小,來將你的緩沖區當中的數據拷貝過去,有多大緩沖區就拷貝多少,緩沖區滿了就立即返回,這個時候的返回值,
只表示拷貝到緩沖區多少數據,但是并不代表發送多少數據,同時剩下的部分需要你再次調用send才會再一次拷貝到底層緩沖區。
【iambic】:
和write差不多。
【Arthur_】:
You can use *setsockopt* to enlarge the buffer.
作為一個套接字,它擁有兩個緩沖,接收數據緩沖和發送數據緩沖(此緩沖不同與你自己定義的緩沖),當有數據到達時,首先進入的
就是接收數據緩沖,然后用戶從這個緩沖中將數據讀出來,這就是套接字接受的過程,這個緩沖的大小可以自己用SetSocketOpt()設定,
同時操作系統對它有一個默認大小,如果對方在很短時間內發送大量數據到達這個套接子時,可能它沒來得及接收完,因此接收緩沖處于
滿的狀態,再有數據來的時候就進不去了,因此對方的 SEND可能就返回錯誤,在對方發送的數據量很小時不會出現這種情況,當數據量很大時,情況就很明顯了,很容易造成收不到的情況。
同樣,發送方的發送緩沖也有相對應的問題。
解決這個問題的辦法有幾種:
1:利用SetSocketOpt()函數將接收方套接子接收緩沖設為足夠大小;
2:在發送方進行數據發送時判斷發送是否成功,如果不成功重發;
3:要求接收方收到數據后給發送方回應,發送方只在收到回應后才發送下一條數據。
總結
以上是生活随笔為你收集整理的send 和recv详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1m照片的宽和高是多少_1m等于多少kb
- 下一篇: oracle both from,Ora