四、Socket類
Socket類表現了客戶端套接字,它是屬於一台或兩台計算機的兩個TCP通訊端口之間的通訊通道。端口可以連接到本地系統的另一個端口,這樣可以避免使用另一台計算機,但是大多數網絡軟件將使用兩台計算機。但是TCP套接字不能與兩台以上的計算機通訊。如果需要這種功能,客戶端應用程序必須建立多個套接字連接,每台計算機一個套接字。
構造函數
Java.Net.Socket類有幾個構造函數。其中兩個構造函數允許使用布爾型參數指定是否使用UDP或TCP套接字,我們不贊成使用它們。這兒沒有使用這兩個構造函數,並且沒有列舉在此處--如果需要UDP功能,請使用DatagramSocket。
try
{
// 連接到指定的主機和端口
Socket mySocket = new Socket ( "www.awl.com", 80);
// ......
}
catch (Exception e)
{
System.err.println ("Err - " + e);
}
但是還有很多構造函數可以用於不同的情形。除非特別指出,所有的構造函數都是公共的。
· protected Socket ()-使用當前套接字產生組件提供的默認實現建立不連接的套接字。開發者一般不應該使用這個方法,因為它不允許指定主機名稱和端口。
· Socket (InetAddress address, int port)產生 Java.io.IOException異常。
· Java.lang.SecurityException-建立連接到指定的IP地址和端口的套接字。如果不能建立連接,或連接到主機違反了安全性約束條件(例如某個小的服務程序試圖連接到某台計算機而不是載入它的計算機時),就產生這種異常。
· Socket (InetAddress address, int port, InetAddress localAddress, int localPort)產生java.io.IOException、Java.lang.SecurityException異常-建立連接到指定的地址和端口的套接字,並把它綁定到特定的本地地址和本地端口。默認情況下,使用一個自由(空)的端口,但是在多地址主機環境(例如本地主機有兩個或多個的計算機)中,該方法也允許你指定一個特定的端口號、地址。
· protected Socket (SocketImpl implementation)--使用特定的套接字的實現(implementation)建立未連接的套接字。通常情況下開發者不應該使用這個方法,因為它允許指定主機名稱和端口。
· Socket (String host, int port)產生Java.Net.UnknownHostException、java.io.IOException、 Java.lang.SecurityException異常--建立連接到特定主機和端口的套接字。這個方法允許指定一個字符串而不是一個 InetAddress。如果指定的主機名稱不能夠解析,就不能建立連接,如果違反了安全性約束條件就產生異常。
· Socket (String host, int port, InetAddress localAddress, int localPort)產生Java.Net.UnknownHostException、java.io.IOException、 Java.lang.SecurityException異常--建立連接到特定主機和端口的套接字,並綁定到特定的本地端口和地址。它允許指定字符串形式的主機名稱,而不是指定InetAddress實例,同時它允許指定一個將綁定的本地地址和端口。這些本地參數對於多地址主機(如果可以通過兩個或更多 IP地址訪問的計算機)是有用的。如果主機名稱不能解析,就不能建立連接,如果違反了安全性約束條件會產生異常。
1、建立套接字
在正常環境下,建立套接字的時候它就連接了某台計算機和端口。盡管有一個空的構造函數,它不需要主機名稱或端口,但是它是受保護的(protected),在正常的應用程序中不能夠調用它。此外,不存在用於在以後指定這些細節信息的connect()方法,因此在正常的環境下建立套接字的時候就應該連接了。如果網絡是好的,在建立連接的時候,調用套接字構造函數將立即返回,但是如果遠程計算機沒有響應,構造函數方法可能會阻塞一段時間。這是隨著系統的不同而不同的,它依賴於多種因素,例如正在使用的操作系統和默認的網絡超時設置(例如本地局域網中的一些計算機一般比Internet 上的計算機響應得快)。你甚至不能肯定套接字將阻塞多長的時間,但是這是非正常的行為,並且它不會頻繁出現。即使如此,在關鍵事務系統中把此類調用放在第二個線程中或許更合適,這樣可以防止應用程序停止。
注意
在較低的層次,套接字是由套接字產生組件(socket factory)產生的,它是一個負責建立適當的套接字實現的特殊的類。在正常環境下,將會產生標准的java.net.Socket,但是在一些特殊的情形中,例如使用自定義套接字的特殊的網絡環境(例如通過使用特殊的代理服務器穿透防火牆),套接字產生組件實際上可能返回一個套接字子類(subclass)。對於錯綜復雜的Java網絡編程比較熟悉,明確為了建立自定義套接字和套接字產生組件的有經驗的開發者可以去了解套接字產生組件的細節信息。對於這個主題的更多信息,你可以查看java.net.SocketFactory和Java.Net.SocketImplFactory類的Java API文檔。
2、使用套接字
套接字可以執行大量的事務,例如讀取信息、發送數據、關閉連接、設置套接字選項等等。此外,下面提供的方法可以獲取套接字的信息(例如地址和端口位置):
方法
· void close()產生Java.io.IOException異常--關閉套接字連接。關閉連接可能允許也可能不允許繼續發送剩余的數據,這依賴於SO_LINGER套接字選項的設定。我們建議開發者在關閉套接字連接之前清除所有的輸出流。
· InetAddress getInetAddress()--返回連接到套接字的遠程主機的地址。
· InputStream getInputStream()產生Java.io.IOException異常--返回一個輸入流,它從該套接字連接到的應用程序讀取信息。
· OutputStream getOutputStream()產生Java.io.IOException異常--返回一個輸出流,它向套接字連接到的應用程序寫入信息。
· boolean getKeepAlive()產生Java.Net.SocketException異常--返回SO_KEEPALIVE套接字選項的狀態。
· InetAddress getLocalAddress()--返回與套接字關聯的本地地址(在多地址計算機中有用)。
· int getLocalPort()--返回該套接字綁定在本地計算機上的端口號。
· int getPort()--返回套接字連接到的遠程服務的端口號。
· int getReceiveBufferSize()產生Java.Net.SocketException異常--返回套接字使用的接收緩沖區大小,由SO_RCVBUF套接字選項的值決定。
· int getSendBufferSize()產生Java.Net.SocketException異常--返回套接字使用的發送緩沖區大小,由SO_SNDBUF套接字選項的值決定。
· int getSoLinger()產生Java.Net.SocketException異常--返回SO_LINGER套接字選項的值,它控制連接終止的時候未發送的數據將排隊多長時間。
· int getSoTimeout()產生Java.Net.SocketException異常--返回SO_TIMEOUT套接字選項的值,它控制讀取操作將阻塞多少毫秒。如果返回值為0,計時器就被禁止了,該線程將無限期阻塞(直到數據可以使用或流被終止)。
· boolean getTcpNoDelay()產生Java.Net.SocketException異常--如果TCP_NODELAY套接字選項的設置打開了返回"true",它控制是否允許使用Nagle算法。
· void setKeepAlive(boolean onFlag)產生Java.Net.SocketException異常--允許或禁止SO_KEEPALIVE套接字選項。
· void setReceiveBufferSize(int size)產生Java.Net.SocketException異常--修改SO_RCVBUF套接字選項的值,它為操作系統的網絡代碼推薦用於接收輸入的數據的緩沖區大小。並不是每種系統都支持這種功能或允許絕對控制這個特性。如果你希望緩沖輸入的數據,我們建議你改用 BufferedInputStream或BufferedReader。
· void setSendBufferSize(int size)產生Java.Net.SocketException異常--修改SO_SNDBUF套接字選項的值,它為操作系統的網絡代碼推薦用於發送輸入的數據的緩沖區大小。並不是每種系統都支持這種功能或允許絕對控制這個特性。如果你希望緩沖輸入的數據,我們建議你改用 BufferedOutputStream或Buffered Writer。
· static void setSocketImplFactory (SocketImplFactory factory)產生Java.Net.SocketException、java.io.IOException、Java. lang.SecurityException異常--為JVM指定一個套接字實現的產生組件,它可以已經存在,也可能違反了安全性約束條件,無論是哪種情況都會產生異常。只能指定一個產生組件,當建立套接字的時候都會使用這個產生組件。
· void setSoLinger(boolean onFlag, int duration)產生Java.Net. SocketException、Java.lang.IllegalArgumentException異常--激活或禁止SO_LINGER套接字選項(根據布爾型參數onFlag的值),並指定按秒計算的持續時間。如果指定負值,將產生異常。
· void setSoTimeout(int duration)產生Java.Net.SocketException異常--修改SO_TIMEOUT套接字選項的值,它控制讀取操作將阻塞多長時間(按毫秒計)。0值會禁止超時設置,引起無限期阻塞。如果發生了超時,當套接字的輸入流上發生讀取操作的時候,會產生 Java.io.IOInterruptedException異常。這與內部的TCP計時器是截然不同的,它觸發未知報文包的重新發送過程。
· void setTcpNoDelay(boolean onFlag)產生Java.Net.SocketException異常--激活或禁止TCP_NODELAY套接字選項,它決定是否使用Nagle算法。
· void shutdownInput()產生Java.io.IOException異常--關閉與套接字關聯的輸入流,並刪除所有發送的更多的信息。對輸入流的進一步的讀取將會遭遇流的結束標識符。