InetAddress:IP 位址封裝。Socket:客戶端通訊端點。ServerSocket:伺服端監聽端點。public class Server {
private int port;
public Server(int port) { this.port = port; start(); }
public String process(String line) { return line.toUpperCase(); }
public void start() {
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("伺服器啟動,監聽埠:" + port);
System.out.println("等待客戶連線...");
try (Socket connection = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
PrintWriter out = new PrintWriter(connection.getOutputStream(), true)) {
System.out.println("客戶連線請求...");
out.println("您好,伺服器連線成功!");
out.println("輸入 bye 斷開連線");
String line;
while ((line = in.readLine()) != null) {
System.out.println("收自客戶:" + line);
String msg = process(line);
out.println("伺服器回應:" + msg);
if (line.trim().equalsIgnoreCase("BYE")) break;
}
}
} catch (Exception e) { e.printStackTrace(); }
}
}
public class Client {
private String host; private int port;
public Client(String host, int port) { this.host = host; this.port = port; connect(); }
public void connect() {
try (Socket connection = host.equals("localhost") ?
new Socket(InetAddress.getLocalHost(), port) :
new Socket(InetAddress.getByName(host), port);
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(connection.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
System.out.println("伺服器:" + in.readLine());
System.out.println("伺服器:" + in.readLine());
System.out.print("請輸入> ");
String line;
while ((line = stdin.readLine()) != null) {
out.println(line);
if (line.equalsIgnoreCase("bye")) break;
System.out.println("伺服器:" + in.readLine());
if (!line.equalsIgnoreCase("bye")) System.out.print("請輸入> ");
}
} catch (IOException e) { System.out.println("連線錯誤:" + e.getMessage()); }
}
}
public class Server extends ServerSocket {
public Server(int port) throws IOException {
super(port);
System.out.println("伺服器啟動,監聽埠:" + port);
try {
while (true) {
Socket conn = accept(); // 阻塞等待
new ServerThread(conn, port); // 每連線一執行緒
}
} finally { close(); }
}
}
public class ServerThread extends Thread {
private Socket connection;
private BufferedReader in;
private PrintWriter out;
public ServerThread(Socket s, int port) throws IOException {
this.connection = s;
in = new BufferedReader(new InputStreamReader(s.getInputStream(), "GB2312"));
out = new PrintWriter(s.getOutputStream(), true);
out.println("您好,伺服器連線成功!");
out.println("輸入 bye 斷開連線");
start();
}
@Override
public void run() {
try {
String line;
while ((line = in.readLine()) != null) {
if (line.trim().equalsIgnoreCase("bye")) break;
System.out.println("收自客戶:" + line);
out.println("伺服器回應:" + line.toUpperCase());
}
System.out.println("Bye bye!");
} catch (Exception e) { e.printStackTrace(); }
finally { try { connection.close(); } catch (IOException ignored) {} }
}
}
與點對點版本相同,無需修改即可連線多執行緒伺服端。
| 特性 | 點對點 | 點對多(多執行緒) |
|---|---|---|
| 伺服端處理 | 單一連線,循環讀寫 | 主執行緒 accept(),每連線啟動 ServerThread |
| 並發能力 | 一次只能服務一個客戶 | 可同時服務多個客戶 |
| 資源關閉 | 手動 close() | 建議用 try-with-resources 或 finally 確保釋放 |
# 伺服端
javac server/*.java
java server.ServerDemo 8888
# 客戶端
javac client/*.java
java client.ClientDemo localhost 8888