對相關類的簡單介紹 java.nio.*, 據說它提供了一些更加底層的一些功能,如:類似windows環境下的AsyncSocket類的異步操作的功能,能顯著降低server端程序的線程管理開銷。 因為大多數應用是建立在TCP之上,所以在此只說說SocketChannel,ServerSocketChannel,Selector和ByteBuffer這幾個類.前三個最終都源自channel類。而channel 類,可以理解為在具體I/O或文件對象之上抽象的一個操作對象,我們通過操作channel的讀寫達到對其對應的文件或I/O對象(包括socket)讀寫的目的。讀寫的內容在內存中放在ByteBuffer類提供的緩沖區。總而言之,channel作為一個橋梁,連接了I/O對象和內存中的ByteBuffer,實現了I/O的更高效的存取。 一個基于TCP的服務器端程序,必然有個偵聽端和若干個通信端,它們在nio中由對應的ServerSocketChannel 和SocketChannel類來實現。為了達到異步I/O操作的目的,需要Selector類,它能檢測到I/O對象的狀態。
SocketChannel類是抽象類,通過調用它的靜態函數open(),可生成一個SocketChannel對象,該對象對應一個java.net.Socket,可通過SocketChannel.socket()獲得,而其對應的Socket也可通過調用函數getChannel()得到已建立的相應SocketChannel。 SocketChannel與它的socket是一一對應的。SocketChannel的操作與Socket也很相似.
ServerSocketChannel也是通過調用它的靜態函數open()生成的,只是它不能直接調用bind()函數來綁定一個地址,需要它對應的ServerSocket來完成綁定工作,一般可按如下步驟做:
羅嗦了半天,還是看看最簡單的C/S實現吧,服務器提供了基本的回射(echo)功能,其中提供了較詳細的注釋。
源碼分析
1.服務器端:
在當前目錄下運行: javac AsynServer.java 后,若無編譯出錯,接下來可運行: java AsynServer 或 java AsynServer ×××(端口號) 上述服務程序在運行時,可指定其偵聽端口,否則程序會取8848為默認端口。
2.客戶端的簡單示例:
在當前目錄下運行: javac AsynClient.java 后,若無編譯出錯,確認AsyncServer已經運行的情況下,接下來可運行: java AsynClient hostname 或 java AsynClient hostname ×××(端口號) 并按提示進行操作即可。
總結 總的來說,用nio進行網絡編程還是很有新意的,服務器端軟件能在一個線程中維護與眾多客戶端的通信連接。筆者在本文中試圖用一個典型的回射例子說明如何用nio建立最基本的C/S應用。希望大家能試著用用它。 另外,筆者在實踐中也發現nio在應用中存在的一些難題,比如如何應用SocketChannel的繼承類,以及如何在socketchannel之上應用SSL(Secure Socket Layer)等等,因而希望這篇文章只是拋磚引玉,引起大家對nio作進一步的討論。