對於linux網路程式設計,有很多坑需要我們去踩。在這個時候,我們才會知道理論知識的重要性。無論是哪種語言,網路程式設計都可以寫成厚厚的一本書。舉個例子,比如「當網路斷掉,我們呼叫write去往socket中寫入資料,為什麼返回正常寫入呢?」。所以有空多看看《tcp/ip詳解》,《unix網路程式設計》等經典書籍來補充網路知識。
首先,我們來解決上面的問題。為什麼網路斷了,還能write還是返回成功呢?我們先看write的定義:
#include
ssize_t write
(int fd,
const
void
*buf, size_t count)
;
對於write的返回值,它表示寫入的位元組數。而這個寫入,是寫到哪呢?是成功傳送的意思嗎? 其實並不是,write成功返回,只是buf中的資料被複製到了kernel中的tcp傳送緩衝區。至於資料什麼時候被發往網路,系統呼叫層面不會給予任何保證和通知。
所以,我們並不能直接根據write的返回值來判定傳送成功,這也就是為什麼網路斷掉了,write的返回值和我們希望寫入的值是一樣的。
讀寫操作肯定會涉及阻塞和非阻塞的問題。那write和read在什麼情況下會阻塞呢?當kernel中該socket的傳送緩衝區已滿時write會阻塞。而read呼叫阻塞,通常是傳送端的資料沒有到達。
對於每個socket,擁有自己的傳送緩衝區和接收緩衝區。兩個緩衝區大小都由系統來自動調節,但一般在default和max之間浮動。
預設socket是阻塞的,將乙個socket 設定成非阻塞模式,可以使用fcntl方法:
int flags;if(
(flags =
fcntl
(fd, f_getfl,
null))
<0)
if(fcntl
(fd, f_setfl, flags | o_nonblock)==-
1)
阻塞(預設)和非阻塞模式下read/write行為的區別:read總是在接收緩衝區有資料時立即返回,而不是等到給定的read buffer填滿時返回。只有當接收緩衝區為空時,阻塞模式才會等待,而非阻塞模式下會立即返回-1。
阻塞的write只有在緩衝區足以放下整個buffer時才返回。非阻塞write則是返回能夠放下的位元組數,之後呼叫則返回-1。
對於阻塞的write有個特殊情況:
當write阻塞等待時,對端關閉了socket,則write則會立即將剩餘緩衝區填滿並返回所寫的位元組數,再次呼叫write則會失敗。
Linux深入理解Socket異常
在各種網路異常情況的背後,tcp是怎麼處理的?又是怎樣把處理結果反饋給上層應用的?本文就來討論這個問題。分為兩個場景來討論 建立連線時的異常情況 1 正常情況下 經過三次握手,客戶端連線成功,服務端有乙個新連線到來。2 客戶端連線了服務端未監聽的埠 在這種情況下,服務端會對收到的syn回應乙個rst...
深入理解讀寫鎖 ReadWriteLock原始碼分析
public inte ce readwritelockclass cacheddata downgrade by acquiring read lock before releasing write lock rwl.readlock lock finally try finally class ...
深入理解C語言 深入理解指標
關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...