【Socket网络编程】12. send()、recv()、sendto() 和 recvfrom() 函数解析
send()、recv()、sendto()和recvfrom()函數解析
一般情況下,send()、recv()在TCP協議下使用,sendto()、recvfrom()在UDP協議下使用,也可以在TCP協議下使用,不過用的很少。
1、send()
這里只描述同步socket的send()函數的執行流程。
s:套接字 | buf:存儲發送數據 | len:發送數據長度
當調用該函數時,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信號,進程對該信號的默認處理是進程終止。
2、recv()
這里只描述同步Socket的recv函數的執行流程。
s:套接字 | buf:存儲發送數據 | len:發送數據長度
當應用程序調用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信號,進程對該信號的默認處理是進程終止。
3、sendto() & recvfrom()
在無連接的數據報socket方式下,由于本地socket并沒有與遠端機器建立連接,所以在發送數據時應指明目的地址,sendto()函數原型為:
int sendto(int sockfd,const void *msg,int len,unsigned int flags,const struct sockaddr *to,int tolen );該函數比send()函數多了兩個參數,to表示目地機的IP地址和端口號信息,而tolen常常被賦值為sizeof(struct sockaddr)。sendto() 函數也返回實際發送的數據字節長度或在出現發送錯誤時返回 -1。
recvfrom()的情況與sendto()類似,也需要目的地址,函數原型為:
int recvfrom(int sockfd,void *buf,int len,unsigned int lags,struct sockaddr *from,int *fromlen );from是一個struct sockaddr類型的變量,該變量保存源機的IP地址及端口號。fromlen常置為sizeof(struct sockaddr)。當recvfrom()返回時,fromlen包含實際存入from中的數據字節數。recvfrom()函數返回接收到的字節數或當出現錯誤時返回 -1,并置相應的errno。
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的【Socket网络编程】12. send()、recv()、sendto() 和 recvfrom() 函数解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Socket网络编程】11.网络编程中
- 下一篇: 【C++】32. Boost C++ 库