本文實例講述了Java網路程式設計之簡單的服務端客戶端應用。分享給大家供大家參考。具體如下:
在Java中,我們使用java.net.Socket及其相關類別來完成有關網路的相關功能。 Socket類別非常簡單易用,因為Java技術隱藏了建立網路連線和透過連線發送資料的複雜過程。下面所說的內容只適用於TCP協定。
一、連接到伺服器
我們可以使用Socket類別的建構子來開啟一個套接字,如
Socket sk = new Socket("210.0.235.14",13);
其中,210.0.235.14是一個點分十進位的String對象,表示目的主機的IP位址(或主機名稱), 13表示指定連接目標主機的13埠。這裡的210.0.235.14是位於香港的一個授時伺服器,授時伺服器預設的連接埠一般都是13.
注意,在成功連接到伺服器之前,程式會阻塞。
接下來可以使用Socket類別的getInputStream()方法來得到一個InputStream對象,透過這個物件就可以取得到目標主機給我們寄過來的資訊:
InputStream inStream = sk.getInputStream();
同理,要向目標主機發送數據,則可以呼叫getOutputStream()方法來取得輸出流物件。
下面的範例功能是連接授時伺服器,並將傳回的資訊列印到標準輸出中:
try { Socket sk = new Socket("210.0.235.14",13); sk.setSoTimeout(3000); InputStream inStream = sk.getInputStream(); //得到輸入流物件Scanner sc = new Scanner(inStream); //將資料列印到控制台while(sc.hasNextLine()) { String str = sc.nextLine(); System.out.println("Output : " + str); } sk.close(); } catch(SocketTimeoutException e) //逾時例外{ System.out.println("Time Out!") ; } catch(Exception e) { e.printStackTrace(); }
程式碼中setSoTimeout()方法可以設定逾時時間,也就是如果超過了設定時間還沒有完成讀寫操作,則會拋出SocketTimeoutException,可以透過擷取這個例外來關閉連線。
另外還有一個超時問題是必須解決的,就是這個Socket類別的建構函數
new Socket(host,port);
會一直無限地阻塞下去,直到成功建立了到目標主機的連線為止。這當然不是我們所希望的。我們可以透過以下調用方式解決此問題:
Socket sk = new Socker();sk.connect(new InetSocketAddress(host,port),2000);//設定逾時時間為2秒
二、取得主機位址
InetAddress類別的靜態方法getByName(hostname)可以傳回代表了某個主機位址的InetAddress對象,而這個物件封閉了一個4位元組的序列,也就是主機的IP位址。然後再呼叫getHostAddress()方法回傳一個表示IP位址的String物件.
一些訪問量大的主機名稱通常會對應多個IP位址以實現負載平衡。我們可以呼叫getAllByName()方法來取得所有主機位址,該方法傳回一個InetAddress物件的陣列。
以下是一個簡單的小程序,實現的功能是,如果不在命令列中設定參數,就列印出本地的IP位址,如果指定了主機名,則列印出該主機所有的IP位址:
package cls; import java.net.*; public class ShowIP { public static void main(String[] args) { try { if(args.length > 0) { String hostName = args[0]; //主機名稱InetAddress[ ] addr = InetAddress.getAllByName(hostName); //得到該主機的所有位址//列印輸出至控制台for(InetAddress address : addr) { System.out.println(address.getHostAddress()); } } else { System.out.println(InetAddress.getLocalHost( ).getHostAddress()); } } catch(Exception e) { e.printStackTrace(); } } }
三、伺服器端程式
伺服器端應用程式使用ServerSocket類別來建立套接字,並鐳其綁定至本機連接埠中,如
ServerSocket sock = new ServerSocker(8000);
sock.accept()方法讓程式不停地等待連接,該方法只有當有客戶端連接時才會傳回一個代表了新連接的Socket對象,即該方法會發生阻塞。
這裡一般要為每個連線新開啟一個執行緒為其服務。
以下是一個完整的例子,服務端在8400端口處等待連接,每當連接到來時,新開一個線程為其服務,並將連接信息寫入的日誌文件中:
package cls; import java.io.*; import java.net.*; import java.util.*; public class ServerDemo { /** * @param args */ public static void main(String[] args) { try { //ServerSocket servSocket = new ServerSocket(8000); ServerSocket servSocket = new ServerSocket(8400); int amount = 0; while(true) { Socket client = servSocket.accept(); ++amount; Date time = new Date(); String prompt = time.toString() + ": 第" + amount + "個使用者" + client.getInetAddress().getHostAddress() + " 已連線/n"; System.out.print(prompt); //在控制台輸出訊息ServerDemo.writeLog(prompt); //寫入到檔案中//start a new Thread Thread th = new Thread(new ServThread(client,amount)) ; th.start(); } } catch(Exception e) { e.printStackTrace(); } } //寫入日誌檔public static void writeLog(String str) { File logFile = new File("server-log.txt"); try { FileWriter out = new FileWriter(logFile,true); out.append(str); out.close(); } catch(Exception e) { e. printStackTrace(); } } } /* * 服務執行緒類別*/ class ServThread implements Runnable { private Socket client; private int ix; public ServThread(Socket soc,int ix) { client = soc; this.ix = ix; } public void run() { try { InputStream inStream = client.getInputStream(); OutputStream outStream = cliclient.getOutStream()); ; Scanner recv = new Scanner(inStream); PrintWriter send = new PrintWriter(outStream,true); send.println("歡迎~隨便聊幾句吧! [輸入'bye'關閉聯接]"); while(recv.hasNextLine()) { String str = recv.nextLine(); if(str.equals("bye")) { send.println("See you later ~ ^-^"); break; } send.println("這是個測試程序,現在還沒有什麼功能哦"); } Date time = new Date(); String prompt = time.toString() + ": 第" + ix + "個使用者" + client.getInetAddress().getHostAddress() + " 已中斷連線/n"; System.out.print( prompt); ServerDemo.writeLog(prompt); //寫入到檔案中client.close(); } catch(Exception e) { e.printStackTrace(); } } }
這個程式已經被放到伺服器上,大家可以使用telnet youthol.tk 8400 指令來體驗這個程式了
希望本文所述對大家的java程式設計有幫助。