本例只做簡單功能演示,代碼并不嚴謹,只是說明客戶端如何實現連接服務端簡單代碼。
代碼在集成Eclipse工具下測試編譯運行環境如下圖所示:
客戶端echoClient.java代碼:
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
|
package com.zhengzz.echo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; class EchoC{ private Socket socket; public EchoC() { // TODO Auto-generated constructor stub try { socket = new Socket( "localhost" , 60000 ); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public void Client() { try { BufferedReader br = new BufferedReader( new InputStreamReader(socket.getInputStream())); PrintWriter pw = new PrintWriter(socket.getOutputStream(), true ); BufferedReader lbr = new BufferedReader( new InputStreamReader(System.in)); String linestr = null ; while ((linestr = lbr.readLine()) != null ) { pw.println(linestr); System.out.println(br.readLine()); if (linestr.equals( "bye#" )) { break ; } } } catch (IOException e) { e.printStackTrace(); } } } public class echoClient { public static void main(String[] args) { new EchoC().Client(); } } |
服務端echoServer.java代碼:
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
|
package com.zhengzz.echo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; class EchoS{ private ServerSocket serverSocket; public EchoS() { try { serverSocket = new ServerSocket( 60000 ); } catch (IOException e) { e.printStackTrace(); } } public void Server() { while ( true ) { try { Socket socket = serverSocket.accept(); System.out.println( "client:" + socket.getInetAddress() + ":" + socket.getLocalPort()); BufferedReader br = new BufferedReader( new InputStreamReader(socket.getInputStream())); PrintWriter pw = new PrintWriter(socket.getOutputStream(), true ); String linestr; while ((linestr = br.readLine()) != null ) { System.out.println(linestr); pw.println( "--->" + linestr); } } catch (IOException e) { System.out.println( "連接斷開:(" ); } } } } public class echoServer { public static void main(String[] args) { new EchoS().Server(); } } |
我在Eclipse工具下直接調試結果如下:
下面我們再來看一個 HelloWord 級別的 Java Socket 通信的例子。通訊過程:
先啟動 Server 端,進入一個死循環以便一直監聽某端口是否有連接請求。然后運行 Client 端,客戶端發出連接請求,服務端監聽到這次請求后向客戶端發回接受消息,連接建立,啟動一個線程去處理這次請求,然后繼續死循環監聽其他請求。客戶端輸入字符串后按回車鍵,向服務器發送數據。服務器讀取數據后回復客戶端數據。這次請求處理完畢,啟動的線程消亡。如果客戶端接收到 "OK" 之外的返回數據,會再次發送連接請求并發送數據,服務器會為這次連接再次啟動一個線程來進行響應。。。直到當客戶端接收到的返回數據為 "OK" 時,客戶端退出。
服務端源代碼:
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
|
package com.defonds.socket.begin; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class Server { public static final int PORT = 12345 ; //監聽的端口號 public static void main(String[] args) { System.out.println( "服務器啟動...\n" ); Server server = new Server(); server.init(); } public void init() { try { ServerSocket serverSocket = new ServerSocket(PORT); while ( true ) { // 一旦有堵塞, 則表示服務器與客戶端獲得了連接 Socket client = serverSocket.accept(); // 處理這次連接 new HandlerThread(client); } } catch (Exception e) { System.out.println( "服務器異常: " + e.getMessage()); } } private class HandlerThread implements Runnable { private Socket socket; public HandlerThread(Socket client) { socket = client; new Thread( this ).start(); } public void run() { try { // 讀取客戶端數據 DataInputStream input = new DataInputStream(socket.getInputStream()); String clientInputStr = input.readUTF(); //這里要注意和客戶端輸出流的寫方法對應,否則會拋 EOFException // 處理客戶端數據 System.out.println( "客戶端發過來的內容:" + clientInputStr); // 向客戶端回復信息 DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.print( "請輸入:\t" ); // 發送鍵盤輸入的一行 String s = new BufferedReader( new InputStreamReader(System.in)).readLine(); out.writeUTF(s); out.close(); input.close(); } catch (Exception e) { System.out.println( "服務器 run 異常: " + e.getMessage()); } finally { if (socket != null ) { try { socket.close(); } catch (Exception e) { socket = null ; System.out.println( "服務端 finally 異常:" + e.getMessage()); } } } } } } |
客戶端源代碼:
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
|
package com.defonds.socket.begin; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; public class Client { public static final String IP_ADDR = "localhost" ; //服務器地址 public static final int PORT = 12345 ; //服務器端口號 public static void main(String[] args) { System.out.println( "客戶端啟動..." ); System.out.println( "當接收到服務器端字符為 \"OK\" 的時候, 客戶端將終止\n" ); while ( true ) { Socket socket = null ; try { //創建一個流套接字并將其連接到指定主機上的指定端口號 socket = new Socket(IP_ADDR, PORT); //讀取服務器端數據 DataInputStream input = new DataInputStream(socket.getInputStream()); //向服務器端發送數據 DataOutputStream out = new DataOutputStream(socket.getOutputStream()); System.out.print( "請輸入: \t" ); String str = new BufferedReader( new InputStreamReader(System.in)).readLine(); out.writeUTF(str); String ret = input.readUTF(); System.out.println( "服務器端返回過來的是: " + ret); // 如接收到 "OK" 則斷開連接 if ( "OK" .equals(ret)) { System.out.println( "客戶端將關閉連接" ); Thread.sleep( 500 ); break ; } out.close(); input.close(); } catch (Exception e) { System.out.println( "客戶端異常:" + e.getMessage()); } finally { if (socket != null ) { try { socket.close(); } catch (IOException e) { socket = null ; System.out.println( "客戶端 finally 異常:" + e.getMessage()); } } } } } } |
注意: Socket 輸出流寫數據方法是 writeUTF 時,輸入流讀取相關數據要用 readUTF。否則會拋 EOFException 異常。