Java 提供 java.net 封裝 TCP/UDP 協議,Socket 代表客戶端連接,ServerSocket 代表服務端監聽。本文聚焦 TCP 可靠流式通信。
// 1. 建立連接(阻塞直到成功或超時)
Socket socket = new Socket();
socket.connect(new InetSocketAddress("host", port), 2000); // 2秒連接超時
socket.setSoTimeout(3000); // 3秒讀寫超時
// 2. 獲取流
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
// 3. 讀寫數據
Scanner scanner = new Scanner(in, "UTF-8");
PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, "UTF-8"), true);
writer.println("Hello Server");
String response = scanner.nextLine();
// 4. 關閉
socket.close();
// 獲取本機 IP
InetAddress local = InetAddress.getLocalHost();
System.out.println(local.getHostAddress());
// 解析域名(支援負載均衡多 IP)
InetAddress[] addresses = InetAddress.getAllByName("google.com");
for (InetAddress addr : addresses) {
System.out.println(addr.getHostAddress());
}
public class TcpServer {
private final int port;
private final ExecutorService pool = Executors.newCachedThreadPool();
public TcpServer(int port) { this.port = port; }
public void start() throws IOException {
try (ServerSocket server = new ServerSocket(port)) {
server.setReuseAddress(true);
System.out.println("Server listening on " + port);
while (!Thread.currentThread().isInterrupted()) {
Socket client = server.accept(); // 阻塞等待連接
pool.execute(new ClientHandler(client));
}
}
}
private static class ClientHandler implements Runnable {
private final Socket socket;
private final int clientId;
private static final AtomicInteger COUNTER = new AtomicInteger();
ClientHandler(Socket socket) {
this.socket = socket;
this.clientId = COUNTER.incrementAndGet();
}
@Override
public void run() {
String clientInfo = socket.getInetAddress() + ":" + socket.getPort();
System.out.println("Client #" + clientId + " connected: " + clientInfo);
try (Scanner in = new Scanner(socket.getInputStream(), "UTF-8");
PrintWriter out = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream(), "UTF-8"), true)) {
out.println("Welcome! Type 'bye' to exit.");
while (in.hasNextLine()) {
String msg = in.nextLine();
if ("bye".equalsIgnoreCase(msg)) {
out.println("Goodbye!");
break;
}
// 業務邏輯:回聲/處理
out.println("Echo: " + msg);
}
} catch (IOException e) {
System.err.println("Client #" + clientId + " error: " + e.getMessage());
} finally {
try { socket.close(); } catch (IOException ignored) {}
System.out.println("Client #" + clientId + " disconnected");
}
}
}
public static void main(String[] args) throws IOException {
new TcpServer(8400).start();
}
}
| 方法 | 作用 | 建議值 |
|---|---|---|
socket.connect(address, timeout) | 連接建立超時 | 2-5 秒 |
socket.setSoTimeout(ms) | 讀操作阻塞超時 | 3-30 秒 |
server.setSoTimeout(ms) | accept() 超時 | 定期檢查關閉標誌 |