Socket 是網絡通信的端點,Java 通過 java.net 包提供豐富的網絡編程 API。本文將系統介紹 InetAddress、TCP、UDP 協議的使用,並演示文件上傳實戰。
InetAddress 類用於表示 IP 地址,提供靜態工廠方法獲取實例:
// 獲取本機地址
InetAddress local = InetAddress.getLocalHost();
String ip = local.getHostAddress(); // IP 字符串
byte[] ipBytes = local.getAddress(); // 原始字節數組
// 通過主機名解析
InetAddress byName = InetAddress.getByName("Livingstone-PC");
// 通過域名解析
InetAddress baidu = InetAddress.getByName("www.baidu.com");
此外,URL 類可直接提取主機信息:new URL("https://localhost:8080/demo.html").getHost()。
TCP 客戶端通過 Socket 建立連接,獲取輸出流發送數據,輸入流接收響應:
Socket socket = new Socket("cj-PC", 10003); // 連接服務端
OutputStream out = socket.getOutputStream(); // 發送數據
out.write("hello".getBytes());
InputStream in = socket.getInputStream(); // 接收響應
byte[] buffer = new byte[1024];
int len = in.read(buffer);
System.out.println(new String(buffer, 0, len));
socket.close(); // 關閉連接,自動釋放流資源
服務端使用 ServerSocket 監聽端口,通過 accept() 阻塞等待客戶端連接:
ServerSocket server = new ServerSocket(10003); // 監聽端口
Socket client = server.accept(); // 接受連接(阻塞)
InputStream in = client.getInputStream();
byte[] buf = new byte[2048];
int len = in.read(buf);
String msg = new String(buf, 0, len);
System.out.println("收到:" + msg);
// 回送確認
OutputStream out = client.getOutputStream();
out.write("收到".getBytes());
client.close(); // 關閉客戶端連接
關鍵點:ServerSocket(int port, int backlog) 可設置最大連接隊列長度;每個客戶端連接建議使用獨立線程處理,避免阻塞主線程。
UDP 通過 DatagramSocket 和 DatagramPacket 實現,適合即時性要求高、容忍丟包的場景。
DatagramSocket socket = new DatagramSocket(8888); // 綁定本地端口
byte[] data = "udp I'm coming".getBytes();
DatagramPacket packet = new DatagramPacket(
data, data.length,
InetAddress.getByName("Machine-Name"), 10086 // 目標地址與端口
);
socket.send(packet);
socket.close();
DatagramSocket socket = new DatagramSocket(10086); // 監聽端口
while (true) {
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet); // 阻塞接收
String ip = packet.getAddress().getHostAddress();
String msg = new String(packet.getData(), 0, packet.getLength());
int port = packet.getPort();
System.out.printf("來自 %s:%d - %s%n", ip, port, msg);
}
利用 FileInputStream 讀取文件,通過 Socket 輸出流分塊發送,最後調用 shutdownOutput() 告知服務端傳輸結束:
// 客戶端
Socket socket = new Socket("Machine-Name", 10005);
OutputStream out = socket.getOutputStream();
FileInputStream fis = new FileInputStream("awf.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
socket.shutdownOutput(); // 關鍵:發送 EOF 信號
// 服務端
ServerSocket server = new ServerSocket(10005);
Socket client = server.accept();
// 建議為每個 client 創建獨立線程處理文件接收
最佳實踐:生產環境應添加進度條、斷點續傳、校驗和異常重試機制。