對於socket發送數據時是否要加鎖及write read的阻塞非阻塞


偶爾討論到了socket發送數據時是否應該加鎖的問題,就在網上查了一下,下面是大神陳碩的答案

  • 對於 UDP,多線程讀寫同一個 socket 不用加鎖,不過更好的做法是每個線程有自己的 socket,避免 contention,可以用 SO_REUSEPORT 來實現這一點。
  • 對於 TCP,通常多線程讀寫同一個 socket 是錯誤的設計,因為有 short write 的可能。假如你加鎖,而又發生 short write,你是不是要一直等到整條消息發送完才解鎖(無論阻塞IO還是非阻塞IO)?如果這樣,你的臨界區長度由對方什么時候接收數據來決定,一個慢的 peer 就把你的程序搞死了。

這里解釋下什么是short write

對於一個非阻塞的TCP套接口,如果其發送緩沖區中根本沒有空間,輸出函數調用將立即返回一個EWOULDBLOCK錯誤。如果其發送緩沖區中有一些空間,返回值將是內核能夠拷貝到該緩沖區中的字節數。這個字節數也稱為不足計數(應該就是short write的意思)

那么陳碩大神的意思是 如果接收方的滑動窗口一直為0,則發送方一直不會發送數據,則會一直持有鎖,就算是非阻塞的,立刻返回后我們就不對接下來的數據進行發送了么?則一直等待在那里

 

socket分為阻塞模式和非阻塞模式。

  阻塞 非阻塞
read 接收緩沖區只要有數據就立即返回,只有當接收緩沖區為空時才阻塞等待 無論有無數據,都立即返回
write 只有發送緩沖區可以放下整個buffer時才返回,否則阻塞 無論發送緩沖區是否能放下整個buffer,都立即返回。返回能夠放下的字節數

1. read總是在接收緩沖區有數據時立即返回,而不是等到給定的read buffer填滿時返回。

只有當receive buffer為空時,blocking模式才會等待,而nonblock模式下會立即返回-1(errno = EAGAIN或EWOULDBLOCK)

2. blocking的write只有在緩沖區足以放下整個buffer時才返回(與blocking read並不相同)

nonblock write則是返回能夠放下的字節數,之后調用則返回-1(errno = EAGAIN或EWOULDBLOCK)

 對於blocking的write有個特例:當write正阻塞等待時對面關閉了socket,則write則會立即將剩余緩沖區填滿並返回所寫的字節數,再次調用則write失敗(connection reset by peer),這正是下個小節要提到的:


免責聲明!

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



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