到底該如何理解socket的阻塞/非阻塞/同步/異步

轉載自:https://blog.csdn.net/voidccc/article/details/8619514

這4個名詞的解釋網絡上有很多種版本和很多種比喻,個人不太喜歡打比方的方式來理解技術問題,因爲很難有貼切的比喻,稍不注意就把人帶到溝裏.我們這裏只通過技術模型來理解這4個術語,忽略這些名詞廣義上的定義,通過分析下面這個具體的場景來分享下我對他們的理解:


場景:假設要通過一個socket發送的數據是5k大小的一段文本,內核的發送緩衝區4k.

首先要搞明白一個基礎問題,當我們在socket上調用一個發送操作時(send/write),雖然我們希望將數據發送到網絡另一端,但是對於操作系統來說,它只要把用戶態的數據成功拷貝到內核的發送緩衝區中排隊等待發送,就可以給用戶態的程序一個最後的交代了,操作系統給用戶態發送的所有通知信息都是表明數據拷貝完成情況的,而操作系統從來不保證你的這些數據已經被網絡另一端讀取到了.即使對方讀取到了,應用層也不會再獲得什麼通知.應用層完全無法獲知數據是否真的到達了網絡另一端.當在一個socket連接上應用寫操作時,最好理解爲拷貝數據到發送隊列中並通知TCP隊列中有了新數據(參考:高級TCP/IP編程15節) 

只從數據角度考慮,socket的發送函數最主要的參數就是一塊用戶態內存(void* buf, int length).對於發送操作(send/write),我們可以從下面兩個方面理解
    1 函數調用完成後 多少數據拷貝完畢
    2 如果發送的數據超出發送緩衝區的大小,調用過程和影響是怎樣的

    1 阻塞
    內核首先將5k裏的前4k數據拷貝到發送緩衝區,4k拷貝完成後,要等待4k中的數據裏最前端的1k數據發送到網絡並且得到了對方SYN確認後,內核確認對方已經收到了這1k的數據,於是將這1k數據從緩衝區中清除,這樣空餘出1k的緩衝區,然後內核將剩餘的1k數據拷貝到發送緩衝區,此後send/write返回.注意這裏不會再等待剩餘數據被對端接受才返回,因爲數據已經拷貝到緩衝區,任務完成了可以給用戶態交代了.待send/write返回後,用戶態的5k數據對內核來說已經失效了,因爲5k數據裏的1k已經到達網絡另一端機器的內核緩衝區,4k位於自己的內核緩衝區.用戶態程序可以釋放這5k數據了
    2 非阻塞
    內核將5k裏的前4k數據拷貝到發送緩衝區,4k拷貝完畢後,內核發現發送緩衝區已滿,就不再等待了,直接返回到用戶態,通過send/write返回值告知用戶態有多少數據被成功拷貝到
發送緩衝區.也就是說send/write調用返回後,用戶態前4k數據已經拷貝完畢.目前這4k數據有兩份,用戶態一份發送緩衝區一份,當網絡可用時,內核直接使用發送緩衝區的數據.在writ
e調用返回後用戶態的5k數據裏前4k就可以釋放了,最後1k還必須留着,因爲發送緩衝區裏沒有這1k數據的副本.與阻塞socket不同的是,當發送緩衝區之後因爲數據的發送而有了一些空間的時候,非阻塞socket會通過某種方式(select poll epoll)通知用戶態,這裏不做詳述.
    3 異步
    對於socket來說,異步意味着被send/write的實現體裏(不一定是內核了,異步IO可能是庫來提供的)只能做很少的記錄工作,通常只限於幾個值或指針的拷貝動作,而不能存在大量>的數據拷貝,比如把待發送的數據從用戶態拷到發送緩衝區就屬於大量數據拷貝,因爲數據拷貝是要花費時間的,這個時間不像幾條賦值語句一樣短,算上這個時間這就不叫"同步"了.異步操作只做了記錄工作而已,記錄下了在用戶態的xx地址處有個5k的緩衝區,後續內核要讀取數據就可以將xx地址處的數據拷貝到內核態.也就是說當send/write函數返回時緩衝區沒被拷貝,只記錄下了有這麼個數據塊要發送.當函數返回後,如果你迅速修改了5k緩衝區裏的內容還是有可能會影響到數據發送的,因爲數據還沒有發生拷貝,這裏可以與上面的兩種"同步socket"做對比.前兩種都執行了數據拷貝的工作才返回.當然了發送完成後異步socket也會通過某種方式通知用戶態,這裏也不做詳述
    4 同步
    在日常編程時,不存在一種單獨的socket叫做"同步socket",上面的阻塞和非阻塞就是兩種"同步socket",因爲從行爲上看這兩種socket都要等待數據從用戶緩衝區拷貝到協議棧發
送緩衝區纔會返回,差別僅僅是緩衝區不足時的處理方式不同.只要緩衝區充足時,不管是阻塞還是非阻塞都會執行數據拷貝工作.從這個角度看所謂非阻塞也只是阻塞的時間短一些而已.如果發送的數據小於緩衝區,則阻塞和非阻塞socket的一次調用時間差異不大.總而言之,拷貝數據是需要花一點時間的,所以這兩種socket都是同步socket
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章