socket系列之用戶端socket——Socket類,socket系列用戶端
假設TCP通訊端伺服器端已經建立好並正在監聽用戶端的串連了,那麼用戶端就可以通過Socket類來發起串連。用戶端發起一個串連請求後,就被動地在等待伺服器的響應。這個類同樣位於java.net包中,包含很多方法用於建立串連,操作資料流等。用戶端按以下幾步進行工作:
① 建立一個Socket執行個體,建構函式直接指定遠程伺服器IP跟連接埠,建立一個TCP串連。
② 通過這個Socket執行個體的輸入輸出資料流進行通訊,Socket執行個體都包含一個InputStream對象和OutputStream對象,通過操作這些流就可以實現接收發送資料。
③ 完成通訊後,用Socket執行個體的close()方法關閉串連。
上面瞭解了應用程式層java的工作方式,接著有必要深入研究socket從應用程式層到系統底層是怎麼工作的,應用程式層的這些操作在系統底層是怎麼反應的。2-3-2-3所示,以虛線為分界線,上層位應用程式層,下層為系統底層。整個工作流程可以分為以下幾步:
(1) 首先確定要進行通訊的目標,包括目標IP和目標連接埠。
(2) 根據目標IP跟連接埠,在Java應用程式層建立一個Socket執行個體。
(3) 阻塞等待,準備進行系統底層相關工作。
(4) 建立socket底層資料結構,socket初始狀態為關閉。
(5) 向這個socket填入本地、遠端地址跟連接埠,並向遠程伺服器發送串連請求,此時socket的狀態為正在串連。
(6) 跟遠程伺服器完成3次握手後,就完成了串連的建立,此時的socket狀態為串連建立完成。
(7) 完成應用程式層上的socket執行個體化,接下去可以對這個socket進行操作,以實現通訊。
圖2-3-2-3 Socket底層工作原理
實際的通訊中,用戶端socket中雖然沒有明顯指定用哪個本地連接埠號碼,但其實系統會隨機(一般大於1023)分配一個連接埠號碼,所以每次通訊使用的本地連接埠號碼一般是不同的。另外,由於訊息在網路中傳輸可能延遲,而如果關閉伺服器用戶端socket串連後,又產生同樣地址的伺服器跟用戶端socket,這時在網路中延遲的舊訊息會被誤以為是新串連的訊息發送給新的socket串連,導致錯誤。所以要TCP規範要求兩端都完成關閉握手後,至少要有一個通訊端保持一段時間Time-Wait狀態。一般用戶端的socket完成通訊後會變為Time-Wait狀態,並保持一段時間。在此期間,不允許socket使用這個本地連接埠號碼,應用程式層Java如果試圖用該連接埠號碼建立一個新的socket執行個體,將拋出IOException異常。