JAVA中的TCP通訊(NIO系列二)

在學習NIO之前,需要把基礎的Socket理解清楚,方便後續對比學習。

1. TCP Socket原理解釋

JAVA中的TCP通訊(NIO系列二)

Socket核心讀寫緩衝區

TCP是全雙工,在TCP Socket核心中有傳送Buffer和接收Buffer,接收Buffer負責接收對端資料,等待應用從接收Buffer中讀取,如果應用Socket一直不呼叫read操作,該資料將一直存在。寫操作同樣,寫入send緩衝區中,至於什麼時候send緩衝區內容傳送到對端,需要看對端接收緩衝區條件是否執行,若對端接收緩衝區不足,對端就會限流,防止TCP包流失。上圖1和4表示Socket的read操作,實際是從核心讀緩衝區獲取資料,讀到Socket應用上。上圖2和3表示Socket的write操作,把資料放到系統傳送緩衝區,網路執行就會發送到對端。(write操作後,對端不一定立刻收到資料)

這倆緩衝區域根據系統的不同可能在核心,也可能是TCP協議棧內,大小根據計算機核心的不同有32KB、64KB等,我們這裡預設是64KB的核心吧,方便後面說明BufferSize。

切記,這倆Buffer,不是JVM的

上面有一點比較重要,無論read和write操作,都需要核心緩衝區支援,如果條件不允許,操作是被阻塞的(Blocked)。例如:socket的read操作,如果Rec Buffer中為空,是無法讀的,Blocked。同樣write操作,SendBuffer沒有足夠空間,那麼Write也是Blocked。所以JAVA中這種Socket程式設計效率比較低,屬於BIO程式設計模型。

當你理解了TCP 中Socket在核心中的工作原理,我們就轉到程式設計上,首先請放心,你一定能把Socket程式設計搞清楚,因為都有相應程式碼例項跟上知識點。

2。 TCP知識點以及程式設計對策

在Socket程式設計中有幾點需要注意,

Socket連線斷開,埠不會馬上被釋放

在連線、斷開頻繁的伺服器上,需要設定

ServerSocket setReuseAddress(true),

這樣埠會馬上釋放,可以緊接著使用該埠建立連線。工作中需要注意使用上面的方法設定服務端的埠釋放策略,否則服務端會服務提供服務的。

ServerSocket的構造,不要指定IP,這個在上節的程式碼中有所體現,稍後我會在下面程式碼中再次體現。

ServerSocket在Accept客戶端Socket之前,可以設定setReceiveBufferSize(>64KB),當BufferSize>64KB的時候,接收端在Accept獲得Socket連線的時候,會把自己的接收緩衝區大小告知傳送端,用來提供吞吐。記住,一定在accept

之前

設定,因為獲得Socket連線之後再設定,無法告知傳送對端,起不到作用。(最佳實踐程式碼稍微再次給出)

JDK裡面的ServerSocket沒有SendBufferSize,因為即使有這個介面,你設定了,也不會通知對端,所有無需設定,當然JDK裡面也有沒有這個方法。Client端Socket在連線

之前

可以設定SetReveiveBufferSize(>64KB),並且告知Server端,影響Server端傳送緩衝區。

對端Socket可以在任何時候設定sendBufferSize。

關閉socket連線有兩種方法,socket。close()或者關閉socket的outputStream。

在程式設計上,要始終設定Socket的超時時間。程式碼稍後。

瞭解Nagle演算法,當應用程式稀稀拉拉的產生資料報文,很零碎的那種,該演算法就起作用了,它阻止TCP連續傳送小報文,緩衝起來一起傳送,這樣就會有延遲。注意:該演算法預設啟動。Socket。setTcpNoDelay(boolean),可以設定是否啟用。

以上8點,對應在程式碼上如何體現呢?看下面程式碼截圖:

JAVA中的TCP通訊(NIO系列二)

Server端

JAVA中的TCP通訊(NIO系列二)

Client端

程式碼總結

本節不講述IO相關編碼,但可以告訴大家,想學習IO,必須要心中有個圖。例如:

JAVA中的TCP通訊(NIO系列二)

在JAVA開發中,掌握上面的理論以及程式碼注意事項,已經足夠開發的使用了,當然,你可以瞭解。可以重點學習後面的Selector實現NIO。