java.net 套件提供的網路能力可分為三層抽象:
// 取得本機 InetAddress
InetAddress local = InetAddress.getLocalHost();
// 由主機名/域名解析(單個)
InetAddress byName = InetAddress.getByName("www.example.com");
// 由主機名解析所有位址(負載均衡、CDN 多 IP)
InetAddress[] all = InetAddress.getAllByName("www.google.com");
getHostName():取得主機名(反向 DNS 解析)。getAddress():取得位元組陣列形式 IP(IPv4 4 位元組,IPv6 16 位元組)。isLoopbackAddress()、isLinkLocalAddress()、isSiteLocalAddress():位址類型判斷。
InetAddress addr = InetAddress.getLocalHost();
byte[] ipBytes = addr.getAddress();
if (ipBytes.length == 4) {
System.out.println("IPv4");
int first = ipBytes[0] & 0xFF; // 無符號轉換
if ((first & 0x80) == 0) System.out.println("Class A");
else if ((first & 0xC0) == 0x80) System.out.println("Class B");
else if ((first & 0xE0) == 0xC0) System.out.println("Class C");
else if ((first & 0xF0) == 0xE0) System.out.println("Class D (Multicast)");
else System.out.println("Class E (Reserved)");
} else if (ipBytes.length == 16) {
System.out.println("IPv6");
}
URL url = new URL("https://user:pass@api.example.com:8443/v1/users?id=123#profile");
// 協議://用戶:密碼@主機:埠/路徑?查詢參數#錨點
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
conn.setReadTimeout(10000);
try (OutputStream os = conn.getOutputStream()) {
os.write(jsonBytes);
}
int status = conn.getResponseCode();
try (InputStream is = status < 400 ? conn.getInputStream() : conn.getErrorStream()) {
String response = new String(is.readAllBytes(), StandardCharsets.UTF_8);
}
try (Socket socket = new Socket("host", 8080);
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream()) {
out.write(requestBytes);
out.flush();
byte[] buffer = new byte[4096];
int len = in.read(buffer);
// 處理回應...
}
try (ServerSocket server = new ServerSocket(8080)) {
while (true) {
Socket client = server.accept(); // 阻塞等待
// 建議提交線程池處理,或使用 NIO
executor.submit(() -> handleClient(client));
}
}
| 選項 | 方法 | 用途 |
|---|---|---|
| SO_TIMEOUT | setSoTimeout(ms) | 讀取超時,防止永久阻塞 |
| SO_KEEPALIVE | setKeepAlive(true) | TCP 心跳,檢測死連線 |
| TCP_NODELAY | setTcpNoDelay(true) | 關閉 Nagle 演算法,降低延遲 |
| SO_RCVBUF/SO_SNDBUF | setReceiveBufferSize/setSendBufferSize | 調整系統接收/發送緩衝區 |
| SO_LINGER | setSoLinger(true, seconds) | 關閉時延遲發送未傳完資料 |
// 發送端
try (DatagramSocket socket = new DatagramSocket()) {
byte[] data = "Hello UDP".getBytes();
InetAddress target = InetAddress.getByName("255.255.255.255"); // 廣播
DatagramPacket packet = new DatagramPacket(data, data.length, target, 9999);
socket.send(packet);
}
// 接收端
try (DatagramSocket socket = new DatagramSocket(9999)) {
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet); // 阻塞
String msg = new String(packet.getData(), 0, packet.getLength());
InetAddress sender = packet.getAddress();
}
| 場景 | 推薦 API | 理由 |
|---|---|---|
| 呼叫 REST API、下載檔案 | HttpClient (Java 11+) / OkHttp | 高層封裝、連線池、自動重試、支援 HTTP/2 |
| 自定義 TCP 協議、長連線即時推送 | Netty / NIO SocketChannel | 高效能、事件驅動、編解碼框架 |
| 簡單 TCP 客戶端/伺服器教學/原型 | Socket / ServerSocket | API 直觀、阻塞模型易理解 |
| 廣播發現、DNS、即時遊戲狀態、IoT 傳感器上報 | DatagramSocket / NIO DatagramChannel | 無連線、低延遲、支援多播 |
掌握 Java 網路三大支柱的特性與適用邊界,是構建健壯分散式系統的基石。