簡單來說,網路程式設計就是讓兩台電腦之間能夠互相傳輸資料。對開發者而言,掌握一套程式介面並使用特定的程式模型,就能輕鬆實現網路通訊。Java SDK 提供了相對簡單的 API 來完成這些工作,其中 Socket 就是核心元件之一。
在 Java 中,網路相關的 API 位於 java.net 套件中。只要匯入這個套件,就能開始進行網路程式開發。網路程式設計的基本模型是「客戶端-伺服器模型」:兩個行程之間互相通訊,其中一方必須提供固定位置(伺服器),另一方只需知道這個位置並建立連線(客戶端),雙方即可進行資料交換。
Java 使用 ServerSocket 類別來支援伺服器端功能。當你建立一個 ServerSocket 實例並指定連接埠號,就等於在網路上建立了一個固定位置,讓其他電腦可以連線訪問。
ServerSocket server = new ServerSocket(6789);
連接埠號注意事項:
客戶端使用 Socket 類別主動發起連線請求。建立連線時需要指定伺服器的 IP 位址和連接埠號。
Socket client = new Socket(InetAddress.getLocalHost(), 5678);
Java 提供 InetAddress 類別處理 IP 位址,可透過靜態方法取得本機 IP 或透過主機名稱/IP 取得 InetAddress 實例。
網路資料傳輸本質上是 I/O 操作。Java 提供針對位元組流和 Unicode 字元流的讀寫器,以及緩衝區機制提升效能。透過 Socket 的 getInputStream() 和 getOutputStream() 方法取得原始位元組流,再轉換為方便操作的字元流。
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
import java.io.*;
import java.net.*;
public class MyServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(5678);
Socket client = server.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream());
while (true) {
String str = in.readLine();
System.out.println(str);
out.println("has receive...");
out.flush();
if (str.equals("end")) break;
}
client.close();
}
}
import java.net.*;
import java.io.*;
public class Client {
static Socket server;
public static void main(String[] args) throws Exception {
server = new Socket(InetAddress.getLocalHost(), 5678);
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter out = new PrintWriter(server.getOutputStream());
BufferedReader wt = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String str = wt.readLine();
out.println(str);
out.flush();
if (str.equals("end")) break;
System.out.println(in.readLine());
}
server.close();
}
}
單執行緒伺服器一次只能處理一個客戶端。要支援多客戶端,最直觀的方式是在主迴圈中持續接受新連線:
while (true) {
Socket client = server.accept();
// 處理客戶端通訊...
client.close();
}
但這種方式是「排隊執行」——必須等前一個客戶端結束,下一個才能進入。無法達成真正的並行服務。
使用執行緒讓每個客戶端連線獨立處理,達成真正的並行。建立繼承 Thread 或實作 Runnable 的處理類別,將 Socket 參考傳入,在 run() 方法中處理通訊邏輯。
import java.net.*;
import java.io.*;
public class MultiUser extends Thread {
private Socket client;
public MultiUser(Socket c) {
this.client = c;
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream());
while (true) {
String str = in.readLine();
System.out.println(str);
out.println("has receive...");
out.flush();
if (str.equals("end")) break;
}
client.close();
} catch (IOException ex) {
// 處理例外
}
}
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(5678);
while (true) {
MultiUser mu = new MultiUser(server.accept());
mu.start(); // 啟動執行緒
}
}
}
Java Socket 程式設計核心在於理解「客戶端-伺服器模型」、掌握 ServerSocket/Socket 配合 I/O Stream 的操作。從單一連線進階到多執行緒架構,是建立高併發網路應用的關鍵步驟。實務上還需考慮連線池、非阻塞 I/O (NIO)、安全性等進階主題,但掌握本文基礎概念即可著手開發各類網路應用程式。