在客戶/伺服器系統中,常遇到:客戶端先啟動需等待伺服器啟動後自動連線;通訊中伺服器異常中斷,客戶端需偵測並自動清理連線、回到初始狀態等待伺服器重啟。傳統阻塞式 I/O 難以優雅處理這些非同步情境。
採用 javax.swing.Timer 定期檢查連線狀態,封裝於 NetComm 類別中,對外隱藏定時器細節,提供簡潔 API。狀態變數 net_state:0=離線/待連線,1=已連線/通訊中。
public class NetComm implements ActionListener {
private javax.swing.Timer timer = new javax.swing.Timer(3000, this); // 每 3 秒觸發
private Socket sock;
private InetAddress serverAddr;
private int serverPort;
public static int net_state = 0; // 靜態共享狀態
public NetComm(InetAddress addr, int port) {
this.serverAddr = addr;
this.serverPort = port;
}
// 初始化連線
public void NetComm_Init() {
net_state = 1;
try {
sock = new Socket(serverAddr, serverPort);
} catch (IOException e) {
net_state = 0; // 連線失敗,保持離線狀態
}
timer.start();
}
// 資料收發
public void NetComm_Data() {
try {
OutputStream os = sock.getOutputStream();
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(os));
out.write("java by ghf@china.com");
out.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String str;
while ((str = in.readLine()) != null) {
System.out.println(str); // 處理接收資料
}
in.close();
} catch (IOException e) {
NetComm_Close(); // 異常時關閉資源
net_state = 0; // 回到離線狀態
}
timer.restart(); // 重新啟動定時器
}
// 關閉資源
public void NetComm_Close() {
if (sock != null) {
try { sock.close(); } catch (IOException ignored) {}
}
}
// 定時器事件處理:狀態機核心
@Override
public void actionPerformed(ActionEvent e) {
if (net_state == 0) {
NetComm_Init(); // 離線狀態:嘗試連線
} else {
NetComm_Data(); // 連線狀態:進行資料收發
}
}
}
NetComm,使用者無需感知底層輪詢邏輯。NetComm_Close() 並重置狀態,自動進入下一輪重連嘗試。EventNotifier 介面,於連線建立、斷開、重連成功時通知上層應用,實現解耦。Selector) 或 Netty 等框架,以事件驅動取代輪詢,降低資源佔用與延遲。