socket編程的阻塞模式效率低下,但卻是Java中典型socket編程的精髓。但是,還有其他技術。例如采用異步套接字通道,通過套接字建立通信,這可以大大降低效率。
插座
在典型的套接字編程情況下,即使用 TCP 和 UDP 套接字的情況下,I/O 操作以阻塞和同步模式工作。這意味著當客戶端套接字的線程調用讀取操作時,它會阻塞服務器,直到數據可用。如果底層緩沖區已滿,這也可能會阻止寫入。這使得其他客戶端套接字線程停止,直到通道被釋放。這種類型的通道阻塞顯然是低效的。為了克服這種情況。相反,可以做的是等到線程完成其工作。客戶端套接字可以在服務器提供數據后立即通知;同時,其他線程可以做其他事情,直到來自服務器的數據到達。如果服務器有多個打開的套接字,另一種方法是創建單獨的線程進行通信。無論哪種情況,這都是一種解決方法,而不是適當的解決方案。然而,正如我們將看到的,Java 通過 SocketChannel 為這個問題提供了一個解決方案。
套接字通道
另一方面,套接字通道是與服務器套接字建立通信的非阻塞方式。在這里,我們可以讓一個線程同時與多個打開的連接進行通信。這是通過向 Selector 添加一堆 SocketChannel 來實現的。選擇器對象位于客戶端和服務器之間。客戶端套接字線程通過循環選擇器的 select 方法來獲取套接字通道。它可以通知套接字通道的狀態是否已被接受、接收數據或關閉。這種技術可以在單個線程中與多個客戶端進行通信,而無需維護多個線程和同步的開銷。你可以在圖 1 中看到這一點。
異步套接字通道
支持異步套接字通道的類實際上是 Java NIO API 庫的一部分。思路是通過sockets實現非阻塞異步IO通信。異步 IO 利用回調代碼在 IO 完成時執行,非阻塞的思想是指立即返回的 IO 操作,可以有數據,也可以沒有數據,或者錯誤代碼。這意味著,在從非阻塞通道讀取時,返回值或阻塞通道沒有延遲,直到返回有形的東西。有兩個與異步套接字操作相關的關鍵類。它們是 AsynchronousServerSocketChannel 和 AsynchronousSocketChannel;兩者都可以在名為 java.nio.channels 的包中找到。
AsynchronousServerSocketChannel 類的對象指定偵聽傳入客戶端連接請求的套接字服務器。只有在接受請求后才能開始交互。名為 AsynchronousSocketChannel 的類負責客戶端和服務器兩端的所有建立交互。
普通的,也就是同步套接字連接和異步套接字連接之間的主要區別在于,在后一種情況下,請求者會在每個操作完成后立即得到通知。同步套接字連接不是這種情況,因為在這種情況下,它會阻塞通道,直到請求完成。
由于套接字通道的異步特性,有一個處理程序負責處理套接字操作的成功或失敗狀態。
責任編輯:Rex_08