本文實例講述了Java網絡編程之簡單的服務端客戶端應用。分享給大家供大家參考。具體如下:
在Java中,我們使用java.net.Socket及其相關類來完成有關網絡的相關功能。Socket類非常簡單易用,因為Java技術隱藏了建立網絡連接和通過連接發送數據的復雜過程。下面所說的內容只適用于TCP協議。
一、連接到服務器
我們可以使用Socket類的構造函數來打開一個套接字,如
1
|
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對象,通過這個對象就可以獲取到目標主機給我們發過來的信息:
1
|
InputStream inStream = sk.getInputStream(); |
同理,要向目標主機發送數據,則可以調用getOutputStream()方法來獲取一個輸出流對象。
下面的例子功能是連接授時服務器,并將返回的信息打印到標準輸出中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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類的構造函數
1
|
new Socket(host,port); |
會一直無限地阻塞下去,直到成功建立了到目標主機的連接為止。這當然不是我們所希望的。我們可以通過如下調用方式解決此問題:
1
2
3
|
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地址:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
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類來創建套接字,并鈄其綁定至本地端口中,如
1
|
ServerSocket sock = new ServerSocker( 8000 ); |
sock.accept()方法讓程序不停地等待連接,該方法只有當有客戶端連接時才會返回一個代表了新連接的Socket對象,即該方法會發生阻塞。
這里一般要為每個連接新開啟一個線程為其服務。
下面是一個完整的例子,服務端在8400端口處等待連接,每當連接到來時,新開一個線程為其服務,并將連接信息寫入的日志文件中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
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 = client.getOutputStream(); 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程序設計有所幫助。