原文地址:http://blog.csdn.net/ordeder/article/details/17240221
1. TCP發送接口:send()
TCP發送數據的接口有send,write,sendmsg。在系統內核中這些函數有一個統一的入口,即sock_sendmsg()。由於TCP是可靠傳輸,所以對TCP的發送接口很容易產生誤解,比如sn = send(...); 錯誤的認爲sn的值是表示有sn個字節的數據已經發送到了接收端。其實真相併非如此。
我們知道,TCP的發送和接收在在內核(linux)中是有對應的緩衝的:
struct sock{ ... struct sk_buff_head receive_queue; //接收的數據報隊列 struct sk_buff_head write_queue; //即將發送的數據報隊列 ... }
對於發送端而言,用戶空間調用send(data)等發送接口將數據發送,內核會將data拷貝到內核空間的socket對應的緩衝中,即sock.write_queue。而send()函數的返回值僅僅是表示本次send()調用中成功拷貝的字節數(用戶空間->內核空間對應的sock緩衝隊列)。具體發送和接收端的接收就由TCP協議完成,雖然TCP是可靠傳輸,但是這個前提是發送端和接收端的網絡是連接的,否則你懂得。這樣,對於調用send()發送的用戶而言,如果想要確定接收方是否成功接受數據,就得需要靠其他的辦法查詢。
2. send()阻塞和非阻塞
前面已說過,sn=send(data)負責將數據拷貝到內核空間,而具體發送是有tcp後續完成(這裏面就包括流量控制等)。對已阻塞和非阻塞僅僅是對於數據從用空空間拷貝到內核空間的發送緩衝這段期間而言的。
1. 如果發送緩衝剩餘空間大於欲發送data的字節數,對於阻塞和非阻塞而言都能成功將數據拷貝至內核緩衝,返回的sn即等於欲發送的數據的字節數。
2.如果發送緩衝剩餘空間小於欲發送data的字節數,
a. 那麼阻塞模式會進行阻塞,等待內核緩衝的空閒空間,然後繼續將數據拷貝到內核緩衝中,直到全部拷貝爲止。返回rn即爲data的數據量。
b. 非阻塞模式,當內核發送緩衝被填滿後,立即返回。rn等於data中已被拷貝到發送緩衝的數據量。
3. 如何判定接收成功接收數據?
1.接收端回覆應答信息。
這個方法比較土,但也是比較實用的。
2.計算髮送端sock已發送數據量
可參考:如何判斷TCP數據包是否發送成功 作者提到可以使用 ioctl接口:ioctl(tcp_socket, SIOCOUTQ, &value);