在傳統的 B/S 架構中,HTTP 協議採用「請求-回應」模式,雖然簡化了伺服器設計、降低連線負擔,但無法滿足聊天室、即時通知、股票行情更新等實時推送需求。早期開發者曾嘗試輪詢、長輪詢、長連線甚至 Flash Socket 等方案,但皆有侷限性。HTML5 標準化的 WebSocket 提供了全雙工、低延遲的持久連線,成為現代即時通訊的首選。
Socket(套接字)是網路通訊的端點,應用程式透過 Socket 發送或接收網路請求。它起源於 UNIX 進程間通訊(IPC),英文原意為「插座」,隱喻程式「插上」網路進行資料交換。WebSocket 建立在 TCP 之上,經由 HTTP 協議升級(Upgrade)握手後,雙方即可自由雙向傳輸資料框,無需重複建立連線。
以下展示一個純前端的 WebSocket 客戶端頁面,包含連線、發送、關閉與錯誤處理:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>WebSocket 客戶端示範</title>
</head>
<body>
<div>
<input type="button" id="btnConnection" value="連線" />
<input type="button" id="btnClose" value="關閉" />
<input type="button" id="btnSend" value="發送" />
</div>
<script src="js/jquery-1.11.1.min.js"></script>
<script>
var socket;
if (typeof(WebSocket) === "undefined") {
alert("您的瀏覽器不支援 WebSocket");
return;
}
$("#btnConnection").click(function() {
socket = new WebSocket("ws://192.168.1.2:8888");
socket.onopen = function() { alert("Socket 已開啟"); };
socket.onmessage = function(msg) { alert("收到訊息:" + msg.data); };
socket.onclose = function() { alert("Socket 已關閉"); };
socket.onerror = function() { alert("發生錯誤"); };
});
$("#btnSend").click(function() {
socket.send("來自客戶端的訊息 " + location.href + new Date());
});
$("#btnClose").click(function() { socket.close(); });
</script>
</body>
</html>
JSR 356 定義了 Java EE 環境下的 WebSocket API(javax.websocket.*),Tomcat 7+ 完整實作此規範。透過 @ServerEndpoint 註解,即可將普通 POJO 變為 WebSocket 端點。
@ServerEndpoint("/push")
public class EchoEndpoint {
@OnOpen
public void onOpen(Session session) throws IOException {
// 連線建立邏輯
}
@OnMessage
public String onMessage(String message) {
return "伺服器回應:" + message; // 簡單回傳
}
@OnError
public void onError(Throwable t) {
t.printStackTrace();
}
@OnClose
public void onClose(Session session, CloseReason reason) {
// 連線關閉清理
}
}
@ServerEndpoint("/ws/{user}")
public class WSServer {
private String currentUser;
@OnOpen
public void onOpen(@PathParam("user") String user, Session session) {
currentUser = user;
System.out.println("Connected ... " + session.getId());
}
@OnMessage
public String onMessage(String message, Session session) {
System.out.println(currentUser + ":" + message);
return currentUser + ":" + message; // 廣播或回傳
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
System.out.println(String.format("Session %s closed: %s", session.getId(), closeReason));
}
@OnError
public void onError(Throwable t) {
t.printStackTrace();
}
}
此範例示範如何透過 @PathParam 擷取 URL 路徑中的使用者識別碼,並在 Session 物件中管理連線狀態。@Message(maxMessageSize=6) 等進階註解可限制訊息大小,超過即斷線保護伺服器資源。
部署至 Tomcat 後,啟動專案,瀏覽器開啟客戶端頁面點擊「連線」,若彈出「Socket 已開啟」即代表握手成功。伺服器控制台將印出連線資訊。生產環境建議:
若需相容舊版瀏覽器(IE 9 以下),可考慮 Comet 反向 AJAX 或長連線方案。Java 生態系有成熟框架:
掌握 WebSocket 核心在於理解「連線生命週期」與「訊息框協議」,配合現代框架(如 Spring WebSocket、Netty、Socket.IO)即可構建高併發、低延遲的即時應用。