Java 網路程式設計完整指南
網路程式設計指編寫運行於多台透過網路連接裝置上的程式。java.net 套件提供低層通訊細節,讓開發者專注於解決問題而非通訊協定。
支援的網路協定
- TCP(傳輸控制協定):可靠、連線導向,常用於 Internet(TCP/IP)
- UDP(用戶資料報協定):無連線、資料包導向
Socket 程式設計核心流程
Socket 使用 TCP 提供兩機器通訊機制:
- 伺服器實例化
ServerSocket,綁定埠口監聽
- 伺服器呼叫
accept() 等待客戶端連線
- 客戶端實例化
Socket,指定主機名與埠口請求連線
- 連線建立雙方各獲
Socket 物件,透過 I/O 流通訊
每個 Socket 擁有輸入/輸出流,客戶端輸出連接伺服器輸入,雙向通訊同步進行。
ServerSocket 類別核心建構子與方法
| 建構子 | 說明 |
ServerSocket(int port) | 綁定指定埠口 |
ServerSocket(int port, int backlog) | 指定 backlog(等待佇列長度) |
ServerSocket(int port, int backlog, InetAddress addr) | 指定埠口、backlog、綁定 IP |
ServerSocket() | 建立非綁定 Socket,稍後呼叫 bind() |
| 常用方法 | 說明 |
accept() | 阻塞等待並接受連線,回傳新 Socket |
getLocalPort() | 取得監聽埠口 |
setSoTimeout(ms) | 設定超時(毫秒) |
bind(SocketAddress, backlog) | 綁定特定位址 |
Socket 類別核心建構子與方法
| 建構子 | 說明 |
Socket(String host, int port) | 連接指定主機埠口 |
Socket(InetAddress host, int port) | 連接指定 IP 埠口 |
Socket() | 建立未連線 Socket |
| 常用方法 | 說明 |
getInputStream() | 取得輸入流 |
getOutputStream() | 取得輸出流 |
getInetAddress() | 取得連線位址 |
getPort() | 取得遠端埠口 |
getLocalPort() | 取得本地埠口 |
close() | 關閉 Socket |
InetAddress 類別核心方法
| 方法 | 說明 |
getByName(String host) | 主機名解析 IP |
getLocalHost() | 取得本機 InetAddress |
getHostAddress() | 取得 IP 字串 |
getHostName() | 取得主機名 |
完整客戶端範例:GreetingClient.java
import java.net.*; import java.io.*;
public class GreetingClient {
public static void main(String[] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
DataOutputStream out = new DataOutputStream(client.getOutputStream());
out.writeUTF("Hello from " + client.getLocalSocketAddress());
DataInputStream in = new DataInputStream(client.getInputStream());
System.out.println("Server says " + in.readUTF());
client.close();
} catch (IOException e) { e.printStackTrace(); }
}
}
完整伺服器端範例:GreetingServer.java
import java.net.*; import java.io.*;
public class GreetingServer extends Thread {
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run() {
while (true) {
try {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress() + "\nGoodbye!");
server.close();
} catch (SocketTimeoutException s) { System.out.println("Socket timed out!"); break; }
catch (IOException e) { e.printStackTrace(); break; }
}
}
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
try { new GreetingServer(port).start(); } catch (IOException e) { e.printStackTrace(); }
}
}
執行測試
$ java GreetingServer 6066
Waiting for client on port 6066...
$ java GreetingClient localhost 6066
Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says Thank you for connecting to /127.0.0.1:6066
Goodbye!