通常情況下,服務器不應該只接受一個客戶端請求,而應該不斷地接受來自客戶端的所有請求,所以Java程序通常會通過循環,不斷地調用ServerSocket的accept()方法。
如果服務器端要“同時”處理多個客戶端的請求,因此服務器端需要為每一個客戶端單獨分配一個線程來處理,否則無法實現“同時”。
需求:多個客戶端連接服務器,並進行多次通信
- 每一個客戶端連接成功后,從鍵盤輸入單詞或詞組,並發送非服務器;
- 服務器收到客戶端的消息后,把詞語“反轉”后返回給客戶端;
- 客戶端接收服務器返回的“詞語”,打印顯示;
- 當客戶端輸入“stop”時斷開與服務器的連接;
- 多個客戶端可以同時給服務器發送“詞語”,服務器可以“同時”處理多個客戶端的請求;
- 服務器端要“同時”處理多個客戶端的請求,那么必須使用多線程,每一個客戶端的通信需要單獨的線程來處理。
客戶端程序示例代碼:
1 import java.io.BufferedReader; 2 import java.io.InputStream; 3 import java.io.InputStreamReader; 4 import java.io.OutputStream; 5 import java.io.PrintStream; 6 import java.net.Socket; 7 import java.util.Scanner; 8
9 public class Client { 10
11 public static void main(String[] args) throws Exception { 12 // 1、准備Socket,連接服務器,需要指定服務器的IP地址和端口號
13 Socket socket = new Socket("127.0.0.1", 8888); 14
15 // 2、獲取輸出流,用來發送數據給服務器
16 OutputStream out = socket.getOutputStream(); 17 PrintStream ps = new PrintStream(out); 18
19 // 3、獲取輸入流,用來接收服務器發送給該客戶端的數據
20 InputStream input = socket.getInputStream(); 21 BufferedReader br = new BufferedReader(new InputStreamReader(input)); 22
23 Scanner scanner = new Scanner(System.in); 24 while(true){ 25 System.out.println("輸入發送給服務器的單詞或成語:"); 26 String message = scanner.nextLine(); 27 if(message.equals("stop")){ 28 socket.shutdownOutput(); 29 break; 30 } 31
32 // 4、 發送數據
33 ps.println(message); 34 // 接收數據
35 String feedback = br.readLine(); 36 System.out.println("從服務器收到的反饋是:" + feedback); 37 } 38
39 //5、關閉socket,斷開與服務器的連接
40 scanner.close(); 41 socket.close(); 42 } 43 }
服務器端程序示例代碼:
1 import java.net.ServerSocket; 2 import java.net.Socket; 3
4 public class Server { 5
6 public static void main(String[] args)throws Exception { 7 // 1、准備一個ServerSocket
8 ServerSocket server = new ServerSocket(8888); 9 System.out.println("等待連接..."); 10
11 int count = 0; 12 while(true){ 13 // 2、監聽一個客戶端的連接
14 Socket socket = server.accept(); 15 System.out.println("第" + ++count + "個客戶端連接成功!!"); 16
17 ClientHandlerThread ct = new ClientHandlerThread(socket); 18 ct.start(); 19 } 20
21 //這里沒有關閉server,永遠監聽
22 } 23 }
服務器端處理客戶端請求的線程類示例代碼:
1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 import java.io.PrintStream; 5 import java.net.Socket; 6
7 public class ClientHandlerThread extends Thread{ 8 private Socket socket; 9
10 public ClientHandlerThread(Socket socket) { 11 super(); 12 this.socket = socket; 13 } 14
15 public void run(){ 16
17 try{ 18 //(1)獲取輸入流,用來接收該客戶端發送給服務器的數據
19 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); 20 //(2)獲取輸出流,用來發送數據給該客戶端
21 PrintStream ps = new PrintStream(socket.getOutputStream()); 22 String str; 23 // (3)接收數據
24 while ((str = br.readLine()) != null) { 25 //(4)反轉
26 StringBuilder word = new StringBuilder(str); 27 word.reverse(); 28
29 //(5)返回給客戶端
30 ps.println(word); 31 } 32 }catch(Exception e){ 33 e.printStackTrace(); 34 }finally{ 35 try { 36 //(6)斷開連接
37 socket.close(); 38 } catch (IOException e) { 39 e.printStackTrace(); 40 } 41 } 42 } 43 }