文章來源:aspcn 作者:孫雯
Java連線導向的類
Sockets有兩種主要的操作方式:連線導向的和不需連線的.連線導向的sockets操作就像一部電話,他們必須建立一個串連和一人呼叫.所有的事情在到達時的順序與它們出發時的順序時一樣.不需連線的sockets操作就像是一個郵件投遞,,沒有什麼保證,多個郵件可能在到達時的順序與出發時的順序不一樣.
到底用哪種模式是郵應用程式的需要決定的.如果可靠性更重要的話,用連線導向的操作會好一些.比如檔案伺服器需要他們的資料的正確性和有序性.如果一些資料丟失了,系統的有效性將會失去.一些伺服器,比如間歇性地發送一些資料區塊.如果資料丟了的話,伺服器並不想要再重新發過一次.因為當資料到達的時候,它可能已經過時了.確保資料的有序性和正確性需要額外的操作的記憶體消耗,額外的費用將會降低系統的回應速率.
不需連線的操作使用資料報協議.一個資料報是一個獨立的單元,它包含了所有的這次投遞的資訊.把它想象成一個信封吧,它有目的地址和要發送的內容.這個模式下的socket不需要串連一個目的的socket,它只是簡單地投出資料報.不需連線的操作是快速的和高效的,但是資料安全性不佳.
連線導向的操作使用TCP協議.一個這個模式下的socket必須在發送資料之前與目的地的socket取得一個串連.一旦串連建立了,sockets就可以使用一個流介面:開啟-讀-寫-關閉.所有的發送的資訊都會在另一端以同樣的順序被接收.連線導向的操作比不需連線的操作效率更低,但是資料的安全性更高.
SUN一直是網路建設的支援者,所以在Java中支援sockets就不足為奇了.實際上,Java降低了建立一個sockets程式的難度.每一個傳輸模式都被封裝到了不同的類中.連線導向的類將會首先被我們討論.
在Java中連線導向的類有兩種形式,它們分別是用戶端和伺服器端.用戶端這一部分是最簡單的,所以我們先討論它.
列表9.1列出了一個簡單的用戶端的程式.它向一個伺服器發出一個請求,取回一個HTML文檔,並把它顯示在控制台上.
9.1一個簡單的socket用戶端
import java.io.*;
import java.net.*;
/**
* 一個簡單的從伺服器取回一個HTML頁面的程式
* 注意:merlin是本地機器的名字
*/
public class SimpleWebClient {
public static void main(String args[])
{
try
{
// 開啟一個用戶端socket串連
Socket clientSocket1 = new Socket("merlin", 80);
System.out.println("Client1: " + clientSocket1);
// 取得一個網頁
getPage(clientSocket1);
}
catch (UnknownHostException uhe)
{
System.out.println("UnknownHostException: " + uhe);
}
catch (IOException ioe)
{
System.err.println("IOException: " + ioe);
}
}
/**
*通過建立的串連請求一個頁面,顯示回應然後關閉socket
*/
public static void getPage(Socket clientSocket)
{
try
{
// 需要輸入和輸出資料流
DataOutputStream outbound = new DataOutputStream(
clientSocket.getOutputStream() );
DataInputStream inbound = new DataInputStream(
clientSocket.getInputStream() );
// 向伺服器發出HTTP請求
outbound.writeBytes("GET / HTTP/1.0\r\n\r\n");
// 讀出回應
String responseLine;
while ((responseLine = inbound.readLine()) != null)
{
// 把每一行顯示出來
System.out.println(responseLine);
if ( responseLine.indexOf("") != -1 )
break;
}
// 清除
outbound.close();
inbound.close();
clientSocket.close();
}
catch (IOException ioe)
{
System.out.println("IOException: " + ioe);
}
}
}
回憶一個,一個用戶端向一個正在監聽的伺服器socket發出一個串連.用戶端的sockets是用Socket類建立的.下面的程式建立了一個用戶端的socket並且串連到了一個主機:
Socket clientSocket = new Socket("merlin", 80);
第一個參數是你想要串連的主機的名稱,第二個參數是連接埠號碼.一個主機名稱指定了目的的名稱.連接埠號碼指定了由哪個應用程式來接收.在我們的情況下,必須指定80,因為它是預設的HTTP協議的連接埠.另外的知名的連接埠列在表9.1中,看:
知名的端品:
echo 7
daytime 13
daytime 13
ftp 21
telnet 23
smtp 25
finger 79
http 80
pop3 110
因為Socket類是連線導向的,它提供了一個可供讀寫的流介面.java.io包中的類可以用來訪問一個已串連的socket:
DataOutputStream outbound = new DataOutputStream(
clientSocket.getOutputStream() );
DataInputStream inbound = new DataInputStream( clientSocket.getInputStream()
);
一旦流建立了,一般的流操作就可以做了:
outbound.writeBytes("GET / HTTP/1.0\r\n\r\n);
String responseLine;
while ( (responseLine = inbound.readLine()) != null)
{
System.out.println(responseLine);
}
以上的小程式請求了一個WEB頁面並且把它顯示出來.當程式完成之後,串連必須關閉.
outbound.close();
inbound.close();
clientSocket.close();
注意socket流必須首先關閉.所有的的socket流必須在socket關閉之前關閉.這個小程式非常地簡單,但是所有的用戶端程式都必須遵首下面的基本的步驟:
1.建立用戶端socket串連.
2.得到socket的讀和寫的流.
3.利用流.
4.關閉流.
5.關閉socket.
使用一個伺服器端的socket只是有一點複雜,它將在下面講到.