本範例展示如何使用多線程實現同時為多個客戶端提供服務的伺服器。伺服器監聽 8000 埠,每當有客戶連接,即啟動一條獨立服務執行緒(ServerThread)處理該連接,主執行緒繼續監聽新連接。
// 檔名:moreServer.java
import java.io.*;
import java.net.*;
import java.util.*;
class moreServer {
public static void main(String[] args) throws IOException {
System.out.println("Server starting...\n");
ServerSocket server = new ServerSocket(8000);
while (true) {
Socket sk = server.accept(); // 阻塞等待連接
System.out.println("Accepting Connection...\n");
new ServerThread(sk).start(); // 啟動服務執行緒
}
}
}
class ServerThread extends Thread {
private Socket sk;
ServerThread(Socket sk) { this.sk = sk; }
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
InputStreamReader isr = new InputStreamReader(sk.getInputStream());
in = new BufferedReader(isr);
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(sk.getOutputStream())), true);
while (true) {
String cmd = in.readLine();
System.out.println(cmd);
if (cmd == null) break;
cmd = cmd.toUpperCase();
if (cmd.startsWith("BYE")) {
out.println("BYE");
break;
} else {
out.println("你好,我是伺服器!");
}
}
} catch (IOException e) {
System.out.println(e.toString());
} finally {
System.out.println("Closing Connection...\n");
try {
if (in != null) in.close();
if (out != null) out.close();
if (sk != null) sk.close();
} catch (IOException e) {
System.out.println("close err" + e);
}
}
}
}
// 客戶端測試程式
import java.io.*;
import java.net.*;
class SocketThreadClient extends Thread {
public static int count = 0;
public SocketThreadClient(InetAddress addr) {
count++;
BufferedReader in = null;
PrintWriter out = null;
Socket sk = null;
try {
sk = new Socket(addr, 8000);
InputStreamReader isr = new InputStreamReader(sk.getInputStream());
in = new BufferedReader(isr);
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(sk.getOutputStream())), true);
System.out.println("count:" + count);
out.println("Hello");
System.out.println(in.readLine());
out.println("BYE");
System.out.println(in.readLine());
} catch (IOException e) {
System.out.println(e.toString());
} finally {
try {
if (in != null) in.close();
if (out != null) out.close();
if (sk != null) sk.close();
} catch (IOException e) {}
}
}
}
public class SocketClient {
public static void main(String[] args) throws IOException, InterruptedException {
InetAddress addr = InetAddress.getByName(null);
for (int i = 0; i < 10; i++)
new SocketThreadClient(addr);
Thread.currentThread().sleep(1000);
}
}
此架構展現了經典的「一連接一執行緒」模型,適用於連接數適中的場景。若連接數極大,建議改用執行緒池或 NIO 非阻塞模型。