TCP(Transmission Control Protocol)提供可靠、有序、雙向的位元組串流通道。Java 透過 java.net.Socket(客戶端)與 java.net.ServerSocket(伺服端)實作 TCP 通訊。
package com.socket.tcp.demo;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TcpClient {
public static void main(String[] args) {
String serverHost = "192.168.1.100"; // 伺服端 IP
int serverPort = 10002; // 伺服端埠號
try (Socket socket = new Socket(serverHost, serverPort);
OutputStream out = socket.getOutputStream()) {
String message = "TCP 測試:客戶端發送訊息!";
out.write(message.getBytes("UTF-8"));
out.flush(); // 確保資料送出
System.out.println("訊息已發送:" + message);
} catch (UnknownHostException e) {
System.err.println("找不到主機:" + e.getMessage());
} catch (IOException e) {
System.err.println("I/O 錯誤:" + e.getMessage());
}
}
}
package com.socket.tcp.demo;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
public static void main(String[] args) {
int port = 10002;
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("伺服端啟動,監聽埠號:" + port);
while (true) { // 持續接受客戶端連線
try (Socket clientSocket = serverSocket.accept();
InputStream in = clientSocket.getInputStream()) {
String clientIp = clientSocket.getInetAddress().getHostAddress();
System.out.println("客戶端連線:" + clientIp);
byte[] buffer = new byte[1024];
int len = in.read(buffer);
if (len > 0) {
String message = new String(buffer, 0, len, "UTF-8");
System.out.println("收到訊息 [" + clientIp + "]:" + message);
}
} catch (IOException e) {
System.err.println("處理客戶端錯誤:" + e.getMessage());
}
}
} catch (IOException e) {
System.err.println("伺服端啟動失敗:" + e.getMessage());
}
}
}
ServerSocket.accept() 阻塞等待),再啟動客戶端。new Socket(host, port) 發起連線,底層完成 TCP 三次交握。getOutputStream() 寫入資料。getInputStream() 讀取資料。InputStream 與 OutputStream。getBytes("UTF-8")、接收端 new String(bytes, "UTF-8") 編碼必須一致。| 問題 | 說明與解決方案 |
|---|---|
| 訊息黏包/半包 | TCP 為串流協議,無訊息邊界。解決:定長、分隔符、長度前綴(如 4 bytes length + body)。 |
| 阻塞模式 | read()、accept() 預設阻塞。高併發可用 NIO (Selector) 或線程池處理多客戶端。 |
| 心跳機制 | 長連線需定期發送心跳檢測連線存活,防止防火牆/NAT 斷開閒置連線。 |
| 優雅關閉 | 呼叫 socket.shutdownOutput() 發送 FIN,對端 read 返回 -1,再關閉輸入流與 Socket。 |
Java Socket TCP 程式設計核心在於理解「連線建立 → 串流讀寫 → 資源釋放」流程。實務專案中建議封裝協議編解碼器、採用 Netty 等高效能網路框架處理高併發與黏包問題,提升開發效率與系統穩定性。