目錄
webSocket簡介
連接原理解析:
客戶端API
服務端API(java)
實戰案例
(1)引入依賴
(2)編寫服務端邏輯
(3)注冊配置類
?(4)前端連接 WebSocket 示例
Websocket與其他消息推送對比
總結
????????大家好,我是jstart千語。相信大家或多或少都聽說過webSocket,與http協議都是TCP下的一種通信協議。主要用于客戶端和服務端可以相互通信的協議,與http協議不同,http協議只能由客戶端想服務端發送請求后,服務端才能向客戶端響應消息。而webSocket協議卻可以主動向客戶端發送消息,這就是全雙工通信。
webSocket簡介
????????WebSocket 是一種基于 TCP 的網絡通信協議,設計用于在客戶端(通常是瀏覽器)和服務器之間建立一個持久化的、雙向通信通道。記住最主要的一句話就可以了:實時通信。
????????傳統的 HTTP 協議是 請求-響應模式,不適合實時性要求高的應用。而 WebSocket 允許服務器主動向客戶端推送消息,非常適合用于聊天室、在線游戲、股票行情、實時通知等場景。
全雙工與半雙工通信的區別:
半雙工 | 允許數據在兩個方向上傳輸,但同一個時間段內只允許一個方向上的傳輸 |
全雙工 | 允許數據在兩個方向上同時傳輸 |
特點:
WebSocket 是一種基于 TCP 的雙向通信協議,它與 HTTP 一樣在應用層運行,但一旦連接建立,通信通道就會一直保持開啟。
它具備以下特點:
-
?全雙工通信:客戶端和服務端都可以主動發送消息
-
長連接:連接建立后無需頻繁重連
-
低延遲:沒有 HTTP 多次握手的開銷
-
瀏覽器支持廣泛:現代瀏覽器均已支持
連接原理解析:
- 首先還是會通過TCP的三次握手來建立連接
- 先由http發送一次請求,請求攜帶對應的請求頭,告訴服務端要升級協議
- 如果服務端支持該協議,也響應對應的響應頭,并且響應狀態碼設置為101,表示要切換協議
- 協議切換成功后,就可以使用webSocket進行雙向通信了
建立流程示例:?
客戶端API
示例:
<script>let ws = new WebSocket("ws://localhost/chat")ws.onopen = function(){};ws.onmessage = function(evt){//通過evt.data 可以獲取服務器發送的數據};ws.onclose(){};<script>
服務端API(java)
?Tomcat的7.0.5版本開始支持WebSocket,并且實現了Java WebSocket規范。
Java WebSocket應用由一系列的Endpoint組成。Endpoint是一個java對象,代表WebSocket鏈接的一端,對于服務端,我們可以視為處理具體WebSocket消息的接口。
其中,Endpoint對象就是客戶端與服務端建立連接時就創建的一個對象, 一個客戶端對應一個Endpoint對象。每個客戶端建立時都會創建一個。
Endpoint有兩種定義方式:編程試和注解試:
onOpen? | 當開啟一個新的會話時調用,該方法是客戶端與服務端握手成功后調用的方法 | @onOpen? |
onClose | 當會話關閉時調用 | @onClose |
onError | 當連接過程異常時調用 | @onError |
?如何向客戶端發送消息?
發送消息則由 RemoteEndpoint完成,其實例由 Session維護。
????????通過session.getBasicRemote獲取同步消息發送的實例,然后調用其sendXxx()方法發送消息 ????????通過session.getAsyncRemote獲取異步消息發送實例,然后調用其sendXxx()方法發送消息
實戰案例
(1)引入依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
(2)編寫服務端邏輯
@ServerEndpoint("/ws/chat")
@Component
public class ChatEndpoint {private static final Set<Session> sessions = ConcurrentHashMap.newKeySet();@OnOpenpublic void onOpen(Session session) {sessions.add(session);System.out.println("用戶連接: " + session.getId());}@OnMessagepublic void onMessage(String message, Session session) {System.out.println("收到消息: " + message);// 廣播給所有人for (Session s : sessions) {s.getAsyncRemote().sendText(message);}}@OnClosepublic void onClose(Session session) {sessions.remove(session);System.out.println("用戶斷開: " + session.getId());}@OnErrorpublic void onError(Session session, Throwable error) {System.err.println("錯誤: " + error.getMessage());}
}
(3)注冊配置類
這個類用于識別掃描所有添加了webSocket相關注解的類
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
?(4)前端連接 WebSocket 示例
<script>const socket = new WebSocket("ws://localhost:8080/ws/chat");socket.onopen = () => {console.log("連接已建立");socket.send("你好 WebSocket!");};socket.onmessage = (event) => {console.log("收到消息: " + event.data);};socket.onclose = () => {console.log("連接關閉");};
</script>
Websocket與其他消息推送對比
輪詢方式最常見的就是掃碼登錄流程了,當用戶頁面出現一個二維碼時
輪詢:每隔一兩秒,向服務端發送一次請求,識別該二維碼有沒有被掃描到,服務端響應對應的消息。缺點:當用戶正好在發送某次請求后掃碼,那用戶也要等一兩秒后才能被響應,會有明顯卡頓。
長輪詢:客戶端想服務端發送一次請求,當服務端有數據變更時,二維碼被掃描到,或者請求超時時(一般是30s)才返回信息。
SSE也是支持長連接的,也使用與服務端主動進行消息推送,但瀏覽器的支持沒有webSocket好。而且通信也是單向的。
總結
WebSocket 是現代實時 Web 應用的重要基石,尤其在 Java 后端系統中,可以輕松通過 Spring Boot 快速構建支持高并發、低延遲的通信模塊。
-
加入權限驗證(如 token 登錄校驗)
-
使用 STOMP 協議進行消息分發與訂閱
-
集成 SockJS 以兼容不支持 WebSocket 的客戶端