1. 概述
一個 WebSocket 提供了一個基於事件的、雙向的、全雙工的連接,連接客户端和服務器。WebSocket 通信包括握手、消息傳遞(發送和接收消息)以及關閉連接。
在本教程中,我們將學習如何使用 瀏覽器和其他流行的工具調試 WebSockets。
2. 構建 WebSocket
讓我們首先構建一個 WebSocket 服務器,該服務器將股票報價更新推送到客户端。
2.1. Maven 依賴
首先,聲明 Spring WebSocket 依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.5.4</version>
</dependency>2.2. Spring Boot 配置
接下來,讓我們定義所需的 @Configuration 以啓用 WebSocket 支持:
@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/stock-ticks").withSockJS();
}
}請注意,此配置提供基於消息代理的 WebSocket,並註冊 STOMP 端點。
此外,讓我們創建一個控制器,向訂閲者發送模擬股票更新:
private SimpMessagingTemplate simpMessagingTemplate;
public void sendTicks() {
simpMessagingTemplate.convertAndSend("/topic/ticks", getStockTicks());
}2.3. 客户端 – 用户界面
讓我們構建一個顯示來自服務器的更新的 HTML5 頁面:
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading ...</span>
</div>
接下來,我們使用 SockJS 連接到 WebSocket 服務器:
function connect() {
let socket = new SockJS('/stock-ticks');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
stompClient.subscribe('/topic/ticks', function (ticks) {
...
});
});
}在這裏,我們使用 SockJS 打開一個 WebSocket,然後訂閲主題 /topic/ticks. Eventually, the client consumes and displays the messages on the user interface when the server produces the messages.
2.4. 演示
啓動服務器並打開應用程序在瀏覽器中:
mvn spring-boot:run因此,我們觀察到股票數據每三秒鐘不刷新頁面或服務器輪詢時就發生變化。
目前,我們已經構建了一個接收股票數據於WebSocket接收的應用。接下來,讓我們學習如何調試這個應用。
3. Mozilla Firefox
Mozilla Firefox 具有 WebSocket 檢查器以及其他 Web 開發工具。
在 Firefox 中,可以通過多種方式啓用開發者工具:
- Windows 和 Linux: Ctrl + Shift + I 或 F12 或 應用程序菜單 → 更多工具 → Web 開發者工具
- macOS: Cmd + Opt + I
接下來,點擊 網絡監視器 → WS 以打開 WebSockets 面板:
在 WebSocket 檢查器已啓用的情況下,讓我們進一步探索它。
3.1. Handshake
打開 URL http://localhost:8080 在 Firefox 中。 在開發者工具打開後,我們現在可以看到 HTTP Handshake。 點擊請求以分析 Handshake:
在 Headers 選項卡下,我們看到包含協議升級和其他 WebSocket 標頭,請求和響應標頭。
3.2. 消息交換
隨後,握手後,消息交換開始。 點擊 響應 選項卡以查看消息交換:
在 響應 面板中,一個 顯示了客户端請求和 一個
代表服務器響應。
3.3. 連接終止
在 WebSocket 中,客户端或服務器都可以關閉連接。
首先,讓我們模擬客户端連接終止。 點擊 HTML 頁面上的 斷開連接 按鈕,並查看 響應 選項卡:
在這裏,我們將會看到客户端發出的連接終止請求。
接下來,讓我們關閉服務器以模擬服務器端連接關閉。 連接在服務器不可達時關閉:
RFC6455 – The WebSocket Protocol specifies:
- 1000 – A normal closure
- 1001 – A server is down, or the user has navigated away from the page
Google Chrome 具有 WebSocket 檢查器,它是開發者工具的一部分,與 Firefox 類似。我們可以通過以下幾種方式激活 WebSocket 檢查器:
- Windows 和 Linux: Ctrl + Shift + I 或 Ctrl + Shift + J 或 F12 或 應用程序菜單 → 更多工具 → 開發者工具
- macOS: Cmd + Opt + I
接下來,點擊 網絡 → WS 面板以打開 WebSocket 面板:
4.1. Handshake
請在 Chrome 中打開 URL http://localhost:8080 ,然後在開發者工具中點擊請求:
在 Headers 選項卡下,我們可以看到所有 WebSocket 頭部信息,包括握手過程。
4.2. 消息交換
接下來,讓我們檢查客户端與服務器之間的消息交換。在開發者工具中,點擊“Messages”選項卡:
類似於 Firefox,我們可以查看消息交換,包括 CONNECT 請求、SUBSCRIBE 請求和 MESSAGE 交換。
4.3. 連接終止
最後,我們將調試客户端和服務器端的連接終止。但是,首先,讓我們關閉客户端連接:
我們可以看到客户端和服務器端之間優雅的連接終止。接下來,讓我們模擬服務器終止連接:
成功的連接終止結束了客户端和服務器端之間的消息交換。
5. Wireshark
Wireshark 是最受歡迎、功能最全面、使用最廣泛的網絡協議嗅探工具。接下來,讓我們看看如何使用 Wireshark 嗅探和分析 WebSocket 流量。
5.1. 捕獲網絡流量
與其它工具不同,我們需要先捕獲 Wireshark 的網絡流量,然後進行分析。 讓我們從捕獲網絡流量開始。
在 Windows 中,當我們打開 Wireshark 時,它會顯示所有可用的網絡接口以及實時網絡流量。 因此,選擇正確的網絡接口以捕獲網絡數據包至關重要。
通常,如果 WebSocket 服務器以 localhost (127.0.0.1) 運行,網絡接口將是環回適配器:
要開始捕獲數據包,請雙擊接口。 一旦選擇正確的接口,我們就可以根據協議進一步過濾數據包。
在 Linux 上,使用 tcpdump 命令捕獲網絡流量。 例如,打開一個 shell 終端並使用以下命令生成一個數據包捕獲文件 websocket.pcap:
tcpdump -w websocket.pcap -s 2500 -vv -i lo然後,使用 Wireshark 打開 websocket.pcap 文件。
5.2. Handshake握手
讓我們分析一下捕獲的網絡數據包。首先,由於初始握手在HTTP協議上進行,請篩選包含http 協議的數據包:
為了獲得握手過程的詳細視圖,請右鍵單擊數據包 → 跟蹤 → TCP流 :
5.3. 消息交換
請回想一下,在初始握手之後,客户端和服務器通過 websocket 協議進行通信。因此,我們篩選包含 websocket 的數據包。 剩餘的數據包顯示了連接和消息交換過程:
5.4. 連接終止
首先,讓我們調試客户端連接終止。啓動 Wireshark 捕獲並點擊 HTML 頁面上的 斷開連接 按鈕,並檢查網絡數據包:
同樣,讓我們模擬服務器端連接終止。首先,啓動數據包捕獲,然後關閉 WebSocket 服務器:
6. Postman
截至目前,Postman 對 WebSockets 的支持仍處於 Beta 階段。 但是,我們仍然可以利用它來調試我們的 WebSockets:
打開 Postman,按下 Ctrl + N 或 新建 → WebSocket 請求:
接下來,在 Enter Server URL 文本框中,輸入 WebSocket URL,然後點擊 連接:
6.1. 握手 (Handshake)
連接成功後,在 消息 選項卡中,點擊連接請求以查看握手詳情:
6.2. 消息交換
現在,讓我們檢查客户端與服務器之間的消息交換:
一旦客户端訂閲了主題,我們就可以看到客户端與服務器之間消息的流動。
6.3. 連接終止
接下來,讓我們看看如何調試連接終止,無論是客户端還是服務器端。首先,在 Postman 中點擊 斷開連接 按鈕,以從客户端關閉連接:
同樣,要檢查服務器端連接終止,請關閉服務器:
7. Spring WebSocket 客户端
最後,讓我們使用基於 Spring 的 Java 客户端調試 WebSockets:
WebSocketClient client = new StandardWebSocketClient();
WebSocketStompClient stompClient = new WebSocketStompClient(client);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
StompSessionHandler sessionHandler = new StompClientSessionHandler();
stompClient.connect(URL, sessionHandler);這會創建一個 WebSocket 客户端,然後註冊一個 STOMP 客户端會話處理程序。
接下來,讓我們定義一個擴展 StompSessionHandlerAdapter 的處理程序。 意圖是,StompSessionHandlerAdapter 類不提供任何實現,除了 getPayloadType 方法。 因此,讓我們為這些方法提供有意義的實現:
public class StompClientSessionHandler extends StompSessionHandlerAdapter {
@Override
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
session.subscribe("/topic/ticks", this);
}
// other methods ...
}接下來,當我們運行這個客户端時,我們會得到類似以下的日誌:
16:35:49.135 [WebSocketClient-AsyncIO-8] INFO StompClientSessionHandler - Subscribed to topic: /topic/ticks
16:35:50.291 [WebSocketClient-AsyncIO-8] INFO StompClientSessionHandler - Payload -> {MSFT=17, GOOGL=48, AAPL=54, TSLA=73, HPE=89, AMZN=-5}
在日誌中,我們可以看到連接和消息交換。此外,當客户端運行時,可以使用Wireshark嗅探WebSocket數據包:
8. 結論
在本教程中,我們學習瞭如何使用一些最流行和廣泛使用的工具來調試 WebSockets。 隨着 WebSockets 的使用和普及程度日益增長,我們可以預見調試工具的數量將會增加,並且會變得更加先進。