Linux send與recv函數詳解
1.簡介
#include <sys/socket.h>ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);
- send和recv的前3個參數等同於read和write;
- flags參數值為0或:
| flags |
說明 |
recv |
send |
| MSG_DONTROUTE |
繞過路由表尋找 |
|
• |
| MSG_DONTWAIT |
僅本操作非阻塞 |
• |
• |
| MSG_OOB |
發送或接收帶外資料 |
• |
• |
| MSG_PEEK |
窺看外來訊息 |
• |
|
| MSG_WAITALL |
等待所有資料 |
• |
|
2. send解析
- sockfd:指定發送端通訊端描述符。
- buff: 存放要發送資料的緩衝區
- nbytes: 實際要改善的資料的位元組數
- flags: 一般設定為0
1) send先比較發送資料的長度nbytes和通訊端sockfd的發送緩衝區的長度,如果nbytes > 通訊端sockfd的發送緩衝區的長度, 該函數返回SOCKET_ERROR。
2) 如果nbtyes <= 通訊端sockfd的發送緩衝區的長度,那麼send先檢查協議是否正在發送sockfd的發送緩衝區中的資料,如果是就等待協議把資料發送完,如果協議還沒有開始發送sockfd的發送緩衝區中的資料或者sockfd的發送緩衝區中沒有資料,那麼send就比較sockfd的發送緩衝區的剩餘空間和nbytes。
3) 如果 nbytes > 通訊端sockfd的發送緩衝區剩餘空間的長度,send就一起等待協議把通訊端sockfd的發送緩衝區中的資料發送完。
4) 如果 nbytes < 通訊端sockfd的發送緩衝區剩餘空間大小,send就僅僅把buf中的資料copy到剩餘空間裡(注意:並不是send把通訊端sockfd的發送緩衝區中的資料傳到串連的另一端的,而是協議傳送的。send僅僅是把buf中的資料copy到通訊端sockfd的發送緩衝區的剩餘空間裡)。
5) 如果send函數copy成功,就返回實際copy的位元組數,如果send在copy資料時出現錯誤,那麼send就返回SOCKET_ERROR;如果在等待協議傳送資料時網路斷開,send函數也返回SOCKET_ERROR。
6) send函數把buff中的資料成功copy到sockfd的發送緩衝區的剩餘空間後它就返回了,但是此時這些資料並不一定馬上被傳到串連的另一端。如果協議在後續的傳送過程中出現網路錯誤的話,那麼下一個socket函數就會返回SOCKET_ERROR(每一個除send的socket函數在執行的最開始總要先等待通訊端的發送緩衝區中的資料被協議傳遞完畢才能繼續,如果在等待時出現網路錯誤那麼該socket函數就返回SOCKET_ERROR)。
7) 在unix系統下,如果send在等待協議傳送資料時網路斷開,調用send的進程會接收到一個SIGPIPE訊號,進程對該訊號的處理是進程終止。
2.recv解析
- sockfd: 接收端通訊端描述符
- buff: 用來存放recv函數接收到的資料的緩衝區
- nbytes: 指明buff的長度
- flags: 一般置為0
1) recv先等待sockfd的發送緩衝區的資料被協議傳送完畢,如果協議在傳送sock的發送緩衝區中的資料時出現網路錯誤,那麼recv函數返回SOCKET_ERROR。
2) 如果通訊端sockfd的發送緩衝區中沒有資料或者資料被協議成功發送完畢後,recv先檢查通訊端sockfd的接收緩衝區,如果sockfd的接收緩衝區中沒有資料或者協議正在接收資料,那麼recv就一起等待,直到把資料接收完畢。當協議把資料接收完畢,recv函數就把sockfd的接收緩衝區中的資料copy到buff中(注意:協議接收到的資料可能大於buff的長度,所以在這種情況下要調用幾次recv函數才能把sockfd的接收緩衝區中的資料copy完。recv函數僅僅是copy資料,真正的接收資料是協議來完成的)。
3) recv函數返回其實際copy的位元組數,如果recv在copy時出錯,那麼它返回SOCKET_ERROR。如果recv函數在等待協議接收資料時網路中斷了,那麼它返回0。
4) 在unix系統下,如果recv函數在等待協議接收資料時網路斷開了,那麼調用 recv的進程會接收到一個SIGPIPE訊號,進程對該訊號的預設處理是進程終止。