Java `java.net` 包提供了從底層 Socket 到高層 HTTP/URL 的完整網絡 API。本文系統講解:InetAddress 域名解析、TCP/UDP Socket 通信模型、ServerSocket 服務端編程、URL/URLConnection 資源訪問、數據報編程、協議層次模型,並附帶可運行的客戶端/服務端完整代碼示例。
| 概念 | 說明 |
|---|---|
| IP 地址 | 32 位 (IPv4) / 128 位 (IPv6) 唯一標識,含網絡 ID + 主機 ID |
| 域名系統 (DNS) | 將域名映射為 IP,分佈式層次命名庫 |
| 端口 | 16 位整數 (0-65535),標識進程通信端點。知名端口:HTTP 80, HTTPS 443, FTP 21, SSH 22, SMTP 25 |
| 協議 | 通信雙方遵守的規則。TCP:可靠、面向連接、字節流;UDP:不可靠、無連接、數據報 |
| C/S 模型 | 客戶端發起請求,服務端監聽端口並響應,支持併發多客戶端 |
// 本機地址
InetAddress local = InetAddress.getLocalHost(); // PCOS-10271310/192.168.1.102
// 域名 → IP (DNS 查詢)
InetAddress netEase = InetAddress.getByName("www.163.com"); // www.163.com/222.186.132.123
// IP 字符串 → InetAddress
InetAddress byIp = InetAddress.getByName("192.168.0.22"); // /192.168.0.22
// 批量解析 (負載均衡、CDN 多 IP)
InetAddress[] baidu = InetAddress.getAllByName("www.baidu.com");
// 14.215.177.38, 14.215.177.37 ...
public class TcpServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8888); // 綁定端口,進入監聽
System.out.println("Server started on 8888");
while (true) {
Socket client = server.accept(); // 阻塞等待連接
// 每客戶端一線程處理 (生產用線程池)
new Thread(() -> handle(client)).start();
}
}
static void handle(Socket socket) {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String msg;
while ((msg = in.readLine()) != null) {
System.out.println("Received: " + msg);
out.println("Echo: " + msg); // 應用層協議:換行結尾
}
} catch (IOException e) { e.printStackTrace(); }
}
}
public class TcpClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 8888);
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader console = new BufferedReader(new InputStreamReader(System.in))) {
String line;
while ((line = console.readLine()) != null) {
out.println(line); // 發送
System.out.println("Server: " + in.readLine()); // 接收回顯
}
}
}
}
DatagramSocket socket = new DatagramSocket(9999);
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
while (true) {
socket.receive(packet); // 阻塞接收
String msg = new String(packet.getData(), 0, packet.getLength());
System.out.println(packet.getAddress() + ":" + packet.getPort() + " -> " + msg);
// 回複
byte[] resp = ("ACK: " + msg).getBytes();
DatagramPacket reply = new DatagramPacket(resp, resp.length, packet.getAddress(), packet.getPort());
socket.send(reply);
}
DatagramSocket socket = new DatagramSocket();
InetAddress server = InetAddress.getByName("localhost");
String msg = "Hello UDP";
DatagramPacket packet = new DatagramPacket(msg.getBytes(), msg.length(), server, 9999);
socket.send(packet);
// 接收回複
byte[] buf = new byte[1024];
DatagramPacket resp = new DatagramPacket(buf, buf.length);
socket.receive(resp);
System.out.println(new String(resp.getData(), 0, resp.getLength()));
socket.close();
protocol://host:port/path?query#fragment
http www.ex.com 80 /api/user?id=1 #section
// 方式 1:URL.openStream() 獲取輸入流
URL url = new URL("https://example.com/image.png");
try (InputStream in = url.openStream();
FileOutputStream out = new FileOutputStream("image.png")) {
byte[] buf = new byte[4096];
int len;
while ((len = in.read(buf)) != -1) out.write(buf, 0, len);
}
// 方式 2:URLConnection 獲取更多控制 (Header、重定向、超時)
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(10000);
conn.setRequestProperty("User-Agent", "Java/17");
if (conn.getResponseCode() == 200) {
try (InputStream in = conn.getInputStream()) { /* 讀取 */ }
// 獲取元數據
String contentType = conn.getContentType(); // image/png
long length = conn.getContentLengthLong();
long modified = conn.getLastModified();
}
String encoded = URLEncoder.encode("參數值 with spaces", StandardCharsets.UTF_8);
// 參數值+with+spaces (空格→+,特殊字符→%XX)
| OSI 七層 | TCP/IP 四層 | 功能 | 典型協議/設備 |
|---|---|---|---|
| 7. 應用層 | 應用層 | 用戶接口 | HTTP, FTP, SMTP, DNS |
| 6. 表示層 | 數據格式轉換 | SSL/TLS, JSON, Protobuf | |
| 5. 會話層 | 會話管理 | RPC, WebSocket | |
| 4. 傳輸層 | 傳輸層 | 端到端可靠/不可靠傳輸 | TCP, UDP |
| 3. 網絡層 | 網際層 | 路由、邏輯寻址 | IP, ICMP, 路由器 |
| 2. 數據鏈路層 | 網絡接口層 | 幀封裝、MAC 寻址 | 以太網, WiFi, 交換機 |
| 1. 物理層 | 比特傳輸 | 光纖, 雙絞線, 集線器 |
Socket 工作在傳輸層 (TCP/UDP) 之上,為應用層提供通信端點抽象。
Java 網絡編程從 `InetAddress` 解析開始,核心分兩條線:TCP Socket (可靠流) 與 UDP Datagram (輕量報文),上層封裝 `URL/URLConnection` 簡化 HTTP 資源訪問。掌握協議分層、IO 流轉換、應用層協議設計、併發模型選擇,並善用成熟框架 (Netty, OkHttp, Spring WebClient),即可構建高性能、穩健的網絡應用。