函數作用
我們知道,服務端中有一個接收緩存區,客戶端中有一個發送緩存區,同時每個TCP socket在內核中也都有一個發送緩沖區和一個接收緩沖區,
send()函數的作用就是將客戶端或服務端中的數據拷貝到SOCKET的發送緩存區中
recv()函數的作用就是將SOCKET的接收緩存區中數據拷貝到客戶端或服務端的接收緩存區中
綜上,send()函數和recv()函數只完成應用層到傳輸層的數據搬運,並不直接將數據傳送到數據的另一端去,真正完成數據的傳輸的是協議功能(TCP/UDP)
函數參數
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
sockfd:創建的sockfd文件描述符,
buf:發送數據所在的數據區,
len:發送數據的長度,
flags:標志位默認設置為0
send()函數的返回值
1、成功執行時,返回發送的字節數。
2、失敗則返回SOCKET_ERROR
ssize_t recv ( int sockfd, void *buf, size_t len, int flags);
recv()函數的返回值
1、成功執行時,返回接收到的字節數。
2、若另一端已關閉連接則返回0,這種關閉是對方主動且正常的關閉
3、失敗返回-1,errno被設為以下的某個值
如何判斷數據是否發送成功?
通過send()函數的返回值,應用層只知道數據是否“拷貝”成功,另一端是否接收數據成功僅靠send()函數的返回值是判斷不了的,
對方是否接收數據成功發送端是判斷不了的,如果發送端需要知道接收端是否接收數據成功,需要接收端給發送端返回一個值來確定(應用層面確定數據發送成功)
系統底層確定數據是否發送成功(協議層面確定數據發送成功)
TCP協議會確保數據完整的發送出去,同時保證數據到達接收端的SOCKET接收緩存區
TCP數據報首部包含發送數據包的基本信息,比如數據長度
TCP協議的ACK確認機制
當SOCKET發送緩存區的大小為0的時候,也可以確定數據完全發送出去,buffer.size()==0
補充:
1、滑動窗口在SOCKET的緩存區里面,窗口的大小會根據接收端的處理情況動態變化(保證SOCKET的接收緩沖區不會溢出)
2、TCP 的SOCKET有接收緩存區和發送緩存區,而UDP的socket只有一個接收緩沖區,沒有發送緩沖區,從概念上來說就是只要有數據就發,不管對方是否可以正確接收,所以不緩沖,不需要發送緩沖區。