java.net 包提供了網絡編程基礎支撐,核心三大類分工明確:
本文從高層 URLConnection 切入,逐步深入核心機制。
URLConnection 實例connect()import java.io.*;
import java.net.*;
public class URLClient {
protected URLConnection connection;
public static void main(String[] args) {
URLClient client = new URLClient();
String yahoo = client.getDocumentAt("https://www.yahoo.com");
System.out.println(yahoo);
}
public String getDocumentAt(String urlString) {
StringBuilder document = new StringBuilder();
try {
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
// 流包裝鏈:InputStream → InputStreamReader → BufferedReader
BufferedReader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream())
);
String line;
while ((line = reader.readLine()) != null) {
document.append(line).append("\n"); // 保留原始換行格式
}
reader.close();
} catch (MalformedURLException e) {
System.err.println("無效 URL: " + urlString);
} catch (IOException e) {
System.err.println("連接異常: " + urlString);
}
return document.toString();
}
}
BufferedReader(new InputStreamReader(conn.getInputStream())) 是 Java IO 處理網絡流的標準套路,必須熟練掌握null,無數據時持續阻塞MalformedURLException(URL 格式錯誤)、IOException(網絡/IO 錯誤)需分別捕獲Socket(host, port) 建立連接public class SocketClient {
public static void main(String[] args) throws IOException {
String host = "localhost";
int port = 8888;
try (Socket socket = new Socket(host, port);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput); // 發送
System.out.println("Server: " + in.readLine()); // 接收回顯
}
}
}
}
public class SocketServer {
public static void main(String[] args) throws IOException {
int port = 8888;
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server started on port " + port);
while (true) {
Socket clientSocket = serverSocket.accept(); // 阻塞等待連接
// 單線程處理(生產環境需改為線程池)
new Thread(new ClientHandler(clientSocket)).start();
}
}
}
}
class ClientHandler implements Runnable {
private final Socket socket;
ClientHandler(Socket socket) { this.socket = socket; }
@Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println("Echo: " + inputLine);
}
} catch (IOException e) {
System.err.println("Client handling error: " + e.getMessage());
}
}
}
ExecutorService 替代 new Thread(),控制併發數| 場景 | 推薦方案 | 理由 |
|---|---|---|
| REST API 調用、靜態資源下載 | URLConnection / HttpClient | 高層抽象,自動處理重定向、Cookie、壓縮、連接池 |
| 自定義 TCP 協議、長連接、即時通訊 | Socket + 線程池 / Netty | 完全控制連接生命周期、心跳、二進制協議 |
| 簡單 HTTP POST/GET、文件上傳 | URLConnection | 標準庫無依賴,輕量級 |
| 高性能微服務網關、代理轉發 | Netty / Vert.x | 事件驅動非阻塞,支撐萬級併發 |
Charset(推薦 UTF-8)socket.setSoTimeout(ms) 防止讀取無限阻塞;connection.setConnectTimeout()socket.setSendBufferSize()/setReceiveBufferSize()Java 網絡編程從 URLConnection 的高層便利到 Socket/ServerSocket 的底層掌控,層層遞進。掌握流包裝模式、阻塞特性、併發處理模型與協議設計,是構建穩健網絡應用的基石。現代高併發場景建議直接採用 Netty 等成熟 NIO 框架,但理解原生 Socket 機制仍是排查疑難雜症、優化性能的前提。