java.net.Socket 是 Java 傳統阻塞式 I/O(BIO)的核心類,封裝 TCP 連線。若需非阻塞高併發,請改用 NIO 的 SocketChannel。本文以 BIO 為例,示範完整的客戶端開發流程。
Socket socket = new Socket("78.46.84.171", 80);
Socket socket = new Socket("jb51.net", 80);
建構子會阻塞直到三向交握完成或拋出 IOException(連線超時、拒絕、DNS 失敗等)。生產環境建議設定連線逾時:
Socket socket = new Socket();
socket.connect(new InetSocketAddress("jb51.net", 80), 5000); // 5秒連線逾時
Socket socket = new Socket("jb51.net", 80);
OutputStream out = socket.getOutputStream();
out.write("GET / HTTP/1.1\r\nHost: jb51.net\r\n\r\n".getBytes(StandardCharsets.UTF_8));
out.flush(); // 強制刷新輸出緩衝區,將資料交給作業系統 TCP 發送緩衝區
out.close(); // 關閉輸出流,發送 FIN 封包,但輸入流仍可讀取回應
關鍵提醒:flush() 僅將資料推送至作業系統核心緩衝區,不保證已發送至網路。TCP 何時真正發送取決於 Nagle 演算法、視窗大小等因素。
Socket socket = new Socket("jb51.net", 80);
InputStream in = socket.getInputStream();
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
String chunk = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
System.out.print(chunk);
// 實際應用需依協定解析:定長、分隔符、長度前綴等
}
in.close();
socket.close();
read() 無資料時阻塞,對方關閉連線才回傳 -1| 幀化方式 | 範例 | 適用場景 |
|---|---|---|
| 定長 | 每則固定 1024 位元組 | 簡單二進位協定 |
| 分隔符 | 以 \n、\r\n 結尾 | 文本協定(HTTP 頭部、SMTP) |
| 長度前綴 | 前 4 位元組標示主體長度 | 高效能二進位協定(Protobuf、Thrift) |