recv函數的MSG_PEEK標志介紹


http://www.blogbus.com/gcoder-logs/220779725.html

考慮下面的場景,server向client發送數據"_META_DATA_\r\n_USER_DATA_",要求"\r\n"之前的數據_META_DATA_在第一次recv中接收,剩下的recv調用讀取_USER_DATA_部分的數據。因為tcp是stream協議,並且_META_DATA_數據不是定長的,所以沒有辦法保證一次recv調用不讀到_USER_DATA_部分的數據,除非一次讀取一個字符。這種場景下,recv的MSG_PEEK參數就發揮作用。

 

recv的原型是ssize_t recv(int s, void *buf, size_t len, int flags); 通常flags都設置為0,此時recv函數讀取tcp buffer中的數據到buf中,並從tcp buffer中移除已讀取的數據。把flags設置為MSG_PEEK,僅把tcp buffer中的數據讀取到buf中,並不把已讀取的數據從tcp buffer中移除,再次調用recv仍然可以讀到剛才讀到的數據。

 

針對上面的場景,recv(fd, buf, nbuf, MSG_PEEK) 查看數據,查看"\r\n"的位置pos,再recv(fd, buf, pos+2, 0) 讀取(並移除)數據。

 

上述場景描述的比較極端,畢竟很多時候,就算在一次recv中讀到了_USER_DATA_部分的數據,仍可以先把這部分數據保存起來,添加到后續的recv數據之前,但是如果不同的recv跨越很多函數,保存數據帶來了額外的復雜度。還可以考慮另外的場景,同一個端口支持文本協議和二進制協議,利用MSG_PEEK看一下頭幾個字符,先判斷是文本協議還是二進制協議,再做請求分發,也是不錯的選擇。當然,真正的recv之前調用使用MSG_PEEK導致額外的一次函數調用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM