Socket類
套接字是網絡連接的一個端點。套接字使得一個應用可以從網絡中讀取和寫入數據。放在兩個不同計算機上的兩個應用可以通過連接發送和接受字節流。為了從你的應用發送一條信息到另一個應用,你需要知道另一個應用的IP地址和套接字端口。在Java里邊,套接字指的是java.net.Socket類。
要創建一個套接字,你可以使用Socket類眾多構造方法中的一個。其中一個接收主機名稱和端口號:
public Socket (java.lang.String host, int port)
在這里主機是指遠程機器名稱或者IP地址,端口是指遠程應用的端口號。例如,要連接yahoo.com的80端口,你需要構造以下的Socket對象:
new Socket ("yahoo.com", 80);
一旦你成功創建了一個Socket類的實例,你可以使用它來發送和接受字節流。要發送字節流,你首先必須調用Socket類的getOutputStream方法來獲取一個java.io.OutputStream對象。要發送文本到一個遠程應用,你經常要從返回的OutputStream對象中構造一個java.io.PrintWriter對象。要從連接的另一端接受字節流,你可以調用Socket類的getInputStream方法用來返回一個java.io.InputStream對象。
以下的代碼片段創建了一個套接字,可以和本地HTTP服務器(127.0.0.1是指本地主機)進行通訊,發送一個HTTP請求,並從服務器接受響應。它創建了一個StringBuffer對象來保存響應並在控制台上打印出來。
Socket socket = new Socket("127.0.0.1", "8080");
OutputStream os = socket.getOutputStream();
boolean autoflush = true;
PrintWriter out = new PrintWriter(
socket.getOutputStream(), autoflush);
BufferedReader in = new BufferedReader(
new InputStreamReader( socket.getInputstream() ));
// send an HTTP request to the web server
out.println("GET /index.jsp HTTP/1.1");
out.println("Host: localhost:8080");
out.println("Connection: Close");
out.println();
// read the response
boolean loop = true;
StringBuffer sb = new StringBuffer(8096);
while (loop) {
if ( in.ready() ) {
int i=0;
while (i!=-1) {
i = in.read();
sb.append((char) i);
}
loop = false;
}
Thread.currentThread().sleep(50);
}
// display the response to the out console
System.out.println(sb.toString());
socket.close();
請注意,為了從web服務器獲取適當的響應,你需要發送一個遵守HTTP協議的HTTP請求。假如你已經閱讀了前面一節超文本傳輸協議(HTTP),你應該能夠理解上面代碼提到的HTTP請求。
注意:你可以本書附帶的com.brainysoftware.pyrmont.util.HttpSniffer類來發送一個HTTP請求並顯示響應。要使用這個Java程序,你必須連接到互聯網上。雖然它有可能並不會起作用,假如你有設置防火牆的話。
ServerSocket類
Socket類代表一個客戶端套接字,即任何時候你想連接到一個遠程服務器應用的時候你構造的套接字,現在,假如你想實施一個服務器應用,例如一個HTTP服務器或者FTP服務器,你需要一種不同的做法。這是因為你的服務器必須隨時待命,因為它不知道一個客戶端應用什么時候會嘗試去連接它。為了讓你的應用能隨時待命,你需要使用java.net.ServerSocket類。這是服務器套接字的實現。
ServerSocket和Socket不同,服務器套接字的角色是等待來自客戶端的連接請求。一旦服務器套接字獲得一個連接請求,它創建一個Socket實例來與客戶端進行通信。
要創建一個服務器套接字,你需要使用ServerSocket類提供的四個構造方法中的一個。你需要指定IP地址和服務器套接字將要進行監聽的端口號。通常,IP地址將會是127.0.0.1,也就是說,服務器套接字將會監聽本地機器。服務器套接字正在監聽的IP地址被稱為是綁定地址。服務器套接字的另一個重要的屬性是backlog,這是服務器套接字開始拒絕傳入的請求之前,傳入的連接請求的最大隊列長度。
其中一個ServerSocket類的構造方法如下所示:
public ServerSocket(int port, int backLog, InetAddress bindingAddress);
對於這個構造方法,綁定地址必須是java.net.InetAddress的一個實例。一種構造InetAddress對象的簡單的方法是調用它的靜態方法getByName,傳入一個包含主機名稱的字符串,就像下面的代碼一樣。
InetAddress.getByName("127.0.0.1");
下面一行代碼構造了一個監聽的本地機器8080端口的ServerSocket,它的backlog為1。
new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"));
一旦你有一個ServerSocket實例,你可以讓它在綁定地址和服務器套接字正在監聽的端口上等待傳入的連接請求。你可以通過調用ServerSocket類的accept方法做到這點。這個方法只會在有連接請求時才會返回,並且返回值是一個Socket類的實例。Socket對象接下去可以發送字節流並從客戶端應用中接受字節流,就像前一節"Socket類"解釋的那樣。實際上,這章附帶的程序中,accept方法是唯一用到的方法。