socket編程的write/send函數?
請教下知乎各位大神
在linux socket編程中,向對端發送數據是可用write函數,但是對於write函數的調用有點疑惑,在網上查資料看了看,以下兩種說法:
(1)write函數只是將數據放到發送緩衝區,然後就返回了,之後的發送是由tcp去發送的,也就是說調用了write函數後數據沒有被發送
(2)write函數實現中是層層調用,調用到下層tcp中發送數據後返回
如果是第一種的話,執行完write函數後進程不是就順序執行下面的指令了嗎?系統是從哪裡調度的tcp來發送數據的呢?怎麼保證執行了write函數後數據一定會被tcp發送呢?
一圖勝千言
對於linux來說,每個socket會有自己的send/receive buffer。調用write,只是說將用戶進程的數據,拷貝到了內核的socket buffer裡面,拷貝完之後,就沒有write什麼事了。內核自己會用自己的進程,調用TCP/IP協議棧,把用戶進程的數據發出去。
可以把內核的TCP/IP協議想像成另外一個進程,調用write的時候,只是把數據發給這個進程,這個進程會處理剩下的事情。實際上在早期,TCP/IP協議棧還真是當成一個軟體產品在賣,不過後來主流操作系統都內置了協議棧,這些產品才涼了。
說下我的理解:
socket的send系統調用只是把應用層數據放在了連接的發送緩衝區中,然後應用進程就從系統調用中返回(不考慮緩衝區滿時),執行接下來的指令。
操作系統可以保證在連接發送緩衝區里的數據能夠發送到網路中。
操作系統內部的內核線程會將發送緩衝區中的數據傳遞給網卡驅動程序,由驅動程序將數據發送到網路中。
兩種情況都會發生。
理解這個問題的關鍵詞是:發送/接收窗口,擁塞窗口,發送/接收緩衝區,軟中斷。你的printf也只是把數據寫到stdio的緩衝區,而且stdio的緩衝區通過write寫到內核緩衝區,如果是文件指針,寫到磁碟上還要經過磁碟緩存。
這些你不用擔心,一般內核幫你處理了。大概要注意的是,TCP socket的send緩衝區有自己的timeout,因為默認開啟Nagle演算法,所以緩衝區沒滿的話要等到超時再發送。對實時性有要求可以用setsockopt關閉Nagle演算法。然而對端的接收區也有緩衝區。
操作系統和驅動層會做的。不需要你操心。
不過也可能發到一般連接斷了,或者被RST了,那數據就丟掉了。推薦閱讀:
※Python之Socket通信與線程
※windows 利用socket實現從http下載?
※WebSocket協議:5分鐘從入門到精通
※DAY18:Netty介紹