在TCP/IP
底層的運作必須處理封包、標頭、格式、交握等的細節,這實在不是什麼好差事,為此Berkeley
UNIX提出Socket的概念,將網路連線簡化為資料流(data
stream)的概念,這個資料流在客戶端與伺服端各有一個接口(port),而資料流就像是在一個連接兩接口的纜線中傳遞,程式設計人員使用
Socket的概念來撰寫網路連線程式,只要處理主機資訊與連接埠,而不用關心底層的瑣碎運作。
簡而言之,就如同檔案輸出入一樣,Socket將網路連線也視作一種輸出入的動作,資料的傳遞就像是將資料寫入與讀入。
在Java中提供Socket類別來支援Socket概念,這邊介紹四個建構式:
public Socket(String host, int port)
public Socket(InetAddress host, int port)
public Socket(String host, int port, InetAddress interface, int localPort)
public Socket(InetAddress host, int port, InetAddress interface, int localPort)
除了第一個建構函式必須同時處理UnknownHostException(無法識別主機)與IOException(無法建立連線時)之外,其它的建構式只需處理IOException。
第一與第二個建構式讓您指定遠端主機與連接時所使用的連接埠,而本機的部份則交由程式自行決定,第三與第四個建構函式可以讓您指定遠端與本身的資訊。
您可以直接指定主機名稱來建立Socket物件,然而使用InetAddress會比較有效率,在真正進行Socket連線之前,如果在建立InetAddress物件時無法取得主機資訊,則可以提前進行相關的處理。
下面這個程式可以讓您掃描指定主機上所開啟的連接埠(0~1023),這邊指定本機為對象建立Socket連線,如果某個連接埠有開啟,就會建立連線,此時顯示該連接埠開啟的訊息:
package onlyfun.caterpillar;
import java.io.*; import java.net.*;
public class ScanPort { public static void main(String[] args) { try { String hostname = "localhost"; InetAddress address = InetAddress.getByName(hostname);
for(int i = 0; i < 1024; i++) { try { Socket skt = new Socket(address, i); // 連線表示有開啟 Port System.out.printf("%nPort: %d Opened..", i); skt.close(); } catch(IOException e) { System.out.print("."); // 無法建立連線,沒有開啟 Port } } } catch(UnknownHostException e) { e.printStackTrace(); } } }
在建立了Socket物件之後,可以取得Socket物件的相關資訊,例如:
public InetAddress getInetAddress()
public int getPort()
public int getLocalPort()
public inetAddress getLocalAddress()
以上的方法由上而下分別為取得Socket連接對象位址、連接對象連接埠、本機連接埠、本機位址。
如果要取過Socket物件接受或輸出資訊,可以使用getInputStream()與getOutputStream()兩個方法,就如同檔案I/O
一樣,您只要將它當作串流資料來處理即可,至於網路上的資訊是如何交換的,您並不用得知,Java會自動幫您完成相關的協定確認。
下面這個程式模擬Telnet程式,您可以用它來與遠端主機進行「以行為主」的文字或指令溝通,也就是每下一行文字或指令就按Enter鍵,然後程式會將您的指令傳送出去,並顯示遠端主機的回應訊息,為了同時處理遠端主機的回應與本機使用者的輸入,程式使用多執行緒:
package onlyfun.caterpillar;
import java.io.*; import java.net.*;
public class SocketToStdout implements Runnable { private Socket skt; public SocketToStdout(Socket skt) { this.skt = skt; } public void run() { BufferedReader sktReader; try { sktReader = new BufferedReader( new InputStreamReader(skt.getInputStream())); String sktMessage = null; while((sktMessage = sktReader.readLine()) != null) { System.out.println(sktMessage); }
skt.close(); } catch(IOException e) { System.out.println(e.toString()); } } }
package onlyfun.caterpillar;
import java.io.*; import java.net.Socket;
public class StdInToSocket implements Runnable { private Socket skt; public StdInToSocket(Socket skt) { this.skt = skt; } public void run() { String userInput; BufferedReader stdInReader; PrintStream socketStream;
try { stdInReader = new BufferedReader( new InputStreamReader(System.in)); socketStream = new PrintStream(skt.getOutputStream());
while(true) { if(skt.isClosed()) { break; } userInput = stdInReader.readLine(); socketStream.println(userInput); } } catch(IOException e) { e.printStackTrace(); }
} }
package onlyfun.caterpillar;
import java.io.*; import java.net.*;
public class ConnectDemo { public static void main(String[] args) { String hostname = "localhost"; int port = 23; InetAddress address; BufferedReader buf; String read;
if(args.length > 1) { hostname = args[0]; port = Integer.parseInt(args[1]); }
try { address = InetAddress.getByName(hostname); try { Socket skt = new Socket(address, port); Thread sktToStd = new Thread(new SocketToStdout(skt)); Thread stdToSkt = new Thread(new StdInToSocket(skt)); sktToStd.start(); stdToSkt.start(); } catch (IOException e) { e.printStackTrace(); } } catch(UnknownHostException e) { System.out.println(e.toString()); }
} }
下面的執行結果是連接至FTP站台的測試,可以輸入簡單的ASCII指令跟FTP站台互動(使用FTP協定指令):
java onlyfun.caterpillar.ConnectDemo ftp.isu.edu.tw 21
220-歡迎光臨義守大學檔案伺服器
220-
220-本站提供以下軟體可供下載:
220-*******************************************************************************
220-/pub/BeOS/ BeOS 作業系統
220-/pub/CPAN/ Perl 程式語言 (Comprehensive Perl Archive Network)
220-/pub/CPatch/ 中文化軟體 (收集大量的 Windows 共享軟體與中文化程式)
220-/pub/Documents/ 各類文件收集
220-/pub/FreeBSD/ FreeBSD 作業系統
220-/pub/Game/ 免費遊戲軟體
220-/pub/Hardware/ 硬體驅動程式
220-/pub/Linux/ Linux 作業系統
220-/pub/MsDownload/ 微軟相關軟體更新 (例如 Service Pack 等)
220-/pub/RFC/ Request for Comments (RFC 文件)
220-/pub/Solaris/ Solaris 作業系統
220-/pub/Yesterday/ 昨日小築完整 mirror (收集大量 Windows 相關軟體)
220-*******************************************************************************
220-
220-另外,歡迎使用者多多利用 HTTP 的方式登入,一來有較佳的
220-傳輸效能,介面功能也較為完善,您還可以利用檔案搜尋引擎
220-快速找到您所需求的檔案,網址如下:
220-
220-http://ftp.isu.edu.tw
220
QUIT
221 Goodbye.
|
|