Java Socket 連接服務端時,雖然直接用 IP+Port 直觀簡單,但 connect(SocketAddress) 強制使用 SocketAddress 抽象類(實為 InetSocketAddress)。這看似繁瑣,實則帶來網路地址復用與生命週期解耦的關鍵優勢。
InetSocketAddress,多次連接同一服務端無需重複解析。getRemoteSocketAddress()、getLocalSocketAddress() 在 socket.close() 後仍可調用,返回的 SocketAddress 可直接用於新連接。public SocketAddress getRemoteSocketAddress() // 獲取遠端地址
public SocketAddress getLocalSocketAddress() // 獲取本地綁定地址
未連接時返回 null;已連接並關閉後仍返回有效地址。
public class SocketAddressReuseDemo {
public static void main(String[] args) throws Exception {
// 首次連接,獲取並保存遠端地址
Socket socket1 = new Socket("www.example.com", 80);
SocketAddress remoteAddr = socket1.getRemoteSocketAddress(); // 保存此對象
socket1.close(); // 關閉但地址對象仍有效
// 後續連接直接復用地址對象
Socket socket2 = new Socket();
// 可選:綁定特定本地地址
// socket2.bind(new InetSocketAddress("192.168.1.100", 0));
socket2.connect(remoteAddr); // 直接使用保存的地址
socket2.close();
// 從地址對象提取詳細信息
InetSocketAddress isa = (InetSocketAddress) remoteAddr;
System.out.println("Server Host: " + isa.getHostName());
System.out.println("Server IP: " + isa.getAddress().getHostAddress());
System.out.println("Server Port: " + isa.getPort());
// 獲取本地綁定信息(socket2 已關閉仍可用)
InetSocketAddress localIsa = (InetSocketAddress) socket2.getLocalSocketAddress();
System.out.println("Local IP: " + localIsa.getAddress().getHostAddress());
System.out.println("Local Port: " + localIsa.getPort());
}
}
Server Host: www.example.com
Server IP: 93.184.216.34
Server Port: 80
Local IP: 192.168.1.50
Local Port: 54321
注意:若socket2未顯式bind(),本地端口由系統在 1024~65535 隨機分配,每次運行可能不同。
| 方式 | 地址復用 | 關閉後可用 | 類型安全 | IPv6 兼容 |
|---|---|---|---|---|
| 字符串 IP+Port | 需重新解析/拼接 | 需自行保存字符串 | 無 | 需手動處理格式 |
| SocketAddress | 對象直接復用 | 方法原生支持 | 強類型 | 統一抽象 |
InetSocketAddress 單例,全局復用。SocketAddress 避免重複 DNS 解析。InetSocketAddress 獲取結構化信息。bind() 實現客戶端指定出口 IP/端口(多網卡場景)。SocketAddress 不是多此一舉,而是 Java 網路 API 面向對象設計的體現 —— 將「網路端點」建模為一等公民,賦予其獨立生命週期與復用能力。