一、UDP特點:
- 無連接不可靠:通信雙方不事先建立連接,直接發送數據。
- 數據封裝:將數據封裝在64KB的數據包中,包含接收端的IP和端口。
- UDP通信模型:
- 模型比喻:以拋韭菜為例,發送端像拋韭菜的人,接收端像接韭菜的人,數據如韭菜,數據包如韭菜盤子。
- 模型作用:幫助理解UDP通信過程,后續代碼編寫將嚴格按照此模型進行。
二、 UDP客戶端代碼實現:
- 創建發送端對象:使用
DatagramSocket
類創建,系統會默認分配端口。 - 創建數據包對象:使用
DatagramPacket
類,封裝要發送的數據,需將數據轉成字節數組,指定發送長度、目的地IP和端口。 - 發送數據包:調用
DatagramSocket
對象的send
方法。 - UDP服務端代碼實現:
- 創建接收端對象:使用
DatagramSocket
類,需注冊端口,與客戶端指定的端口匹配。 - 創建數據包對象:使用
DatagramPacket
類,準備字節數組接收數據,大小最好設置為64KB。 - 接收數據:調用
DatagramSocket
對象的receive
方法,將數據封裝到數據包對象的字節數組中。 - 處理數據:獲取收到的數據長度,可通過數據包對象獲取對方的IP和端口。
- 創建接收端對象:使用
- 代碼測試與注意事項:
- 啟動順序:先啟動服務端,再啟動客戶端。
- 資源關閉:客戶端發完數據后應關閉通信管道,服務端不應關閉。
- UDP多發多收實現:
- 客戶端改造:使用
while
死循環,讓用戶不斷輸入數據,封裝成數據包發送,輸入exit
退出。 - 服務端改造:使用
while
死循環,不斷用數據包接收數據。
- 客戶端改造:使用
- 服務端多客戶端接收原理:
- 接收原理:服務端只負責接收流向本機和指定端口的數據包,不管數據來自哪個客戶端,所以可以同時接收多個客戶端的消息。
- 多開客戶端:在IDE中配置允許多開實例,可同時啟動多個客戶端。
三、TCP通信基礎 :
- 特點回顧 :TCP通信是面向連接的可靠通信,采用三次握手建立全雙工可靠連接,能實現端到端通信,服務端確認接收后數據才被認為發送成功。
- 實現方式 :在Java中使用Socket類實現TCP通信,基于IO流進行數據傳輸。
- 通信模型 :通信分客戶端和服務端,需建立Socket端到端的通信管道,通過字節輸入流和輸出流在管道中收發數據。
- 客戶端開發 :
- 創建管道 :創建Socket對象請求與服務端連接,需填寫服務器IP和端口,如使用本地IP可填127.0.0.1,端口可設為9999。
- 發送消息 :從Socket管道獲取字節輸出流,可將其包裝成打印流、緩沖字節輸入流或特殊數據流(DataOutputStream)發送數據,注意流的對應匹配。
- 資源釋放 :實際開發中一般用戶點退出時才關閉管道,一發一收場景可關閉。
- 服務端開發 :
- 創建對象 :使用ServerSocket類創建對象并注冊端口,等待客戶端連接,調用accept方法返回服務端的Socket對象。
- 接收數據 :從Socket管道獲取字節輸入流,包裝成特殊數據輸入流(DataInputStream)接收客戶端數據,先接收整數,再接收消息。
- 獲取信息 :可通過Socket管道獲取客戶端的IP和端口信息。
四、 測試與運行 :
- 啟動順序 :先啟動服務端,服務端在accept方法處阻塞等待客戶端連接,客戶端啟動后雙方建立通信管道。
- 速度差異 :服務端和客戶端執行速度快慢不影響數據接收,數據會緩存到管道中,確保對方收到。
- 多發多收實現 :
- 客戶端改造 :使用死循環讓用戶反復輸入消息,通過Scanner獲取用戶輸入,發exit時關閉管道并退出循環。
- 服務端改造 :將接收消息的邏輯放入死循環,只接收文本消息,服務端不能關閉管道。
- 多客戶端支持 :
- 單線程問題 :當前服務端單線程只能處理一個客戶端消息,加死循環也無法解決。
- 多線程引入 :主線程負責接收客戶端連接,每接到一個管道交給獨立子線程處理消息,定義線程類(如ServerReader)重寫run方法讀取管道消息。
- 上下線追蹤 :服務端可通過接收管道知道客戶端上線,客戶端異常退出或關閉程序時服務端捕獲異常追蹤下線邏輯,可獲取客戶端IP。
五、BS架構原理 :
- 架構特點 :CS架構需開發客戶端和服務端,BS架構客戶端為瀏覽器無需開發,服務端需開發響應網頁。
- 請求與響應 :瀏覽器使用HTTP協議通過IP和端口請求服務端,服務端響應網頁數據需遵循HTTP協議規定的格式,包括協議版本、頭部字段、空行等。
- 代碼開發 :復制之前的服務端代碼進行修改,端口設為8080方便瀏覽器識別,使用打印流響應網頁數據,響應完關閉管道。
- 線程池優化 :
- 優化原因 :每次請求開一個線程處理網站請求不合適,線程工作時間短,創建和銷毀大量線程開銷大,線程池適合處理網站請求。
- 實現方法 :將Socket管道包裝成任務對象(實現Runnable接口)交給線程池處理,創建線程池時設置核心線程數、最大線程數、任務隊列等參數。