五、建立TCP客戶端
討論了套接字類的功能後,我們將分析一個完整的TCP客戶端程序。此處我們將看到的客戶端程序是一個daytime客戶端,它連接到一個daytime服務器程序以讀取當前的日期和時間。建立套接字連接並讀取信息是一個相當簡單的過程,只需要少量的代碼。
<!-- frame contents -->
<!-- /frame contents -->
默認情況下daytime服務運行在13端口上。並非每台計算機都運行了daytime服務器程序,但是Unix服務器是客戶端運行的很好的系統。假如你沒有訪問Unix服務器的權限,在第七部分我們給出了TCP daytime服務器程序代碼--有了這段代碼客戶端就可以運行了。
DaytimeClient的代碼
import Java.net.*
import java.io.*;
public class DaytimeClient
{
public static final int SERVICE_PORT = 13;
public static void main(String args[])
{
// 檢查主機名稱參數
if (args.length != 1)
{
System.out.println ("Syntax - DaytimeClient host");
return;
}
// 獲取服務器程序的主機名稱
String hostname = args[0];
try
{
// 獲取一個連接到daytime服務的套接字
Socket daytime = new Socket (hostname,
SERVICE_PORT);
System.out.println ("Connection established");
// 在服務器程序停止的情況下設置套接字選項
daytime.setSoTimeout ( 2000 );
// 從服務器程序讀取信息
BufferedReader reader = new BufferedReader (
new InputStreamReader
(daytime.getInputStream()
));
System.out.println ("Results : " +
reader.readLine());
// 關閉連接
daytime.close();
}
catch (IOException ioe)
{
System.err.println ("Error " + ioe);
}
}
}
DaytimeClient是如何工作的
Daytime應用程序是很輕易理解的,它使用了文章前面談到的概念。建立套接字、獲取輸入流,在很少的事件中(在連接時像daytime一樣簡單的服務器程序失敗)激活超時設置。不是連接已篩選過的流,而是把有緩沖的讀取程序連接到套接字輸入流,並且把結果顯示給用戶。最後,在關閉套接字連接後客戶端終止。這是你可能得到的最簡單的套接字應用程序了--復雜性來自實現的網絡協議,而不是來自具體網絡的編程。
運行DaytimeClient
運行上面的應用程序很簡單。簡單地把運行daytime服務的計算機的主機名稱作為命令行參數指定並運行它就可以了。假如daytime服務器程序使用了非標准的端口號(在後面會討論),記得需要改變端口號並重新編譯。
例如,假如服務器程序在本機上,為了運行客戶端將使用下面的命令:
java DaytimeClient localhost
注重
Daytime服務器程序必須正在運行中,否則該客戶端程序將不能建立連接。例如假如你正在使用Wintel系統而不是Unix,那麼你需要運行DaytimeServer(後面會談到
六、ServerSocket類
服務器套接字是一種特定類型的套接字,它用於提供TCP服務。客戶端套接字綁定到本地計算機的任何空的端口,並且連接到特定服務器程序的端口和主機。服務器套接字與它的差別是它們綁定到本地計算機的某個特定的端口,這樣遠程客戶端才能定位某種服務。客戶端套接字連接只能連接到一台計算機,然而服務器套接字能夠滿足多個客戶端的請求。
它工作的方法很簡單--客戶端知道服務運行在某個特定的端口(通常端口號是知名的,並且特定的協議使用特定的端口號,但是服務器程序也可能運行在非標准的端口上)。它們建立連接,在服務器程序內部,連接會被接受。服務器程序可以同時接受多個連接,在某個給定的時刻也可以選擇只接受一個連接。某個連接被接受後,它就表現為正常的套接字,形式為Socket對象--一旦你把握了Socket類,編寫服務器程序就和編寫客戶端程序幾乎一樣簡單了。服務器程序和客戶端程序的唯一區別是服務器程序幫定到特定的端口,使用ServerSocket對象。ServerSocket對象就像創建客戶端連接的工廠--你不必親自建立Socket類的實例。這些連接都模擬正常的套接字,因此你能夠把輸入和輸出過濾流關聯到這些連接上。