Contents

调试Websocket

1. 概述

WebSocket 在客户端和服务器之间提供了一个事件驱动的、双向的、全双工的连接。WebSocket 通信涉及握手、消息传递(发送和接收消息)和关闭连接。

在本教程中,我们将学习使用浏览器 和其他流行工具调试 WebSocket 。

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 配置

接下来,让我们定义启用 WebSocket 支持所需的*@Configuration* :

@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。最终,当服务器产生消息时,客户端消费并在用户界面上显示消息。

2.4. 示范

让我们启动服务器并在浏览器中打开应用程序:

mvn spring-boot:run

结果,我们看到股票报价每三秒变化一次,而无需刷新页面或进行服务器轮询:

到目前为止,我们已经构建了一个在 WebSocket 上接收股票报价的应用程序。接下来,让我们学习如何调试这个应用程序。

3. 火狐浏览器

Mozilla Firefox 有一个 WebSocket 检查器以及其他 Web 开发工具。在 Firefox 中,我们可以通过多种方式启用开发者工具:

  • Windows 和 LinuxCtrl + Shift + IF12应用程序菜单 → 更多工具 → Web 开发人员工具
  • macOSCmd + Option + I

接下来,单击Network Monitor → WS打开 WebSockets 窗格:

/uploads/debug_websockets/2.jpg

随着 WebSocket 检查器处于活动状态,让我们进一步探索它。

3.1. 握手

在 Firefox 中打开 URL http://localhost:8080打开开发人员工具后,我们现在可以看到 HTTP 握手。点击请求分析握手:

/uploads/debug_websockets/4.jpg

Headers选项卡下,我们可以看到带有协议升级和其他 WebSocket 标头的请求和响应标头。

3.2. 消息交换

随后,握手之后,消息交换开始。单击Response选项卡以查看消息交换:

/uploads/debug_websockets/6.jpg

在“Response”窗格中,a/uploads/debug_websockets/8.jpg 显示客户端请求,a 表示服务器响应。/uploads/debug_websockets/10.jpg

3.3. 连接终止

在 WebSockets 中,客户端或服务器都可以关闭连接。

首先,让我们模拟客户端连接终止。单击HTML 页面上的Disconnect 按钮并查看Response选项卡:

/uploads/debug_websockets/12.jpg

在这里,我们将看到来自客户端的连接终止请求。

接下来,让我们关闭服务器以模拟服务器端连接关闭。由于无法访问服务器,连接将关闭:

/uploads/debug_websockets/14.jpg

RFC6455 – WebSocket 协议 指定:

  • 1000 – 正常关闭
  • 1001 - 服务器已关闭,或用户已导航离开页面

4. 谷歌浏览器

Google Chrome 有一个 WebSocket 检查器,它是开发人员工具的一部分,类似于 Firefox。我们可以通过以下几种方式激活 WebSocket 检查器:

  • Windows 和 LinuxCtrl + Shift + IF12应用程序菜单 → 更多工具 → 开发工具
  • macOSCmd + Option + I

接下来,点击Network → WS面板打开 WebSocket 面板:

/uploads/debug_websockets/16.jpg

4.1. 握手

现在,在 Chrome 中打开 URL http://localhost:8080 并在开发者工具中点击请求:

/uploads/debug_websockets/18.jpg

Headers选项卡下,我们注意到所有 WebSocket 标头,包括握手。

4.2. 消息交换

接下来,让我们检查客户端和服务器之间的消息交换。在开发人员工具上,单击“*Messages *”选项卡:

/uploads/debug_websockets/20.jpg

和Firefox一样,我们可以查看消息交换,包括CONNECT请求、SUBSCRIBE请求和MESSAGE交换。

4.3. 连接终止

最后,我们将调试客户端和服务器端的连接终止。但是,首先,让我们关闭客户端连接:

/uploads/debug_websockets/22.jpg

我们可以看到客户端和服务器之间的连接正常终止。接下来,让我们模拟一个终止连接的服务器:

/uploads/debug_websockets/24.jpg

成功的连接终止结束客户端和服务器之间的消息交换。

5. Wireshark

Wireshark 是最流行、最广泛和使用最广泛的网络协议嗅探工具。那么接下来,让我们看看如何使用 Wireshark 嗅探和分析 WebSocket 流量。

5.1. 捕获流量

与其他工具不同,我们必须为 Wireshark 捕获流量,然后对其进行分析。所以,让我们从捕获流量开始。

在 Windows 中,当我们打开 Wireshark 时,它会显示所有可用的网络接口以及实时网络流量。因此,选择正确的网络接口来捕获网络数据包至关重要。

*通常,如果 WebSocket 服务器作为*localhost (127.0.0.1)运行,则网络接口将是一个环回适配器

/uploads/debug_websockets/26.jpg

接下来,要开始捕获数据包,请双击该界面。一旦选择了正确的接口,我们就可以根据协议进一步过滤数据包。

在 Linux中,使用tcpdump 命令捕获网络流量。例如,打开一个 shell 终端并使用此命令生成一个数据包捕获文件websocket.pcap

tcpdump -w websocket.pcap -s 2500 -vv -i lo

然后,使用 Wireshark 打开websocket.pcap文件。

5.2. 握手

让我们尝试分析一下目前捕获的网络数据包。首先,由于初始握手是在 HTTP 协议上,让我们过滤http协议的数据包

/uploads/debug_websockets/28.jpg

接下来,要获得握手的详细视图,请右键单击数据包 → FollowTCP Stream

/uploads/debug_websockets/30.jpg

5.3. 消息交换

回想一下,在初始握手之后,客户端和服务器通过 websocket 协议进行通信。 因此,让我们过滤 websocket 的数据包。 显示的其余数据包揭示了连接和消息交换:

/uploads/debug_websockets/32.jpg

5.4. 连接终止

首先,让我们调试客户端连接终止。 启动Wireshark抓包,点击HTML页面上的Disconnect按钮,查看网络数据包:

/uploads/debug_websockets/34.jpg

同样,让我们模拟服务器端连接终止。 首先,启动数据包捕获,然后关闭 WebSocket 服务器:

/uploads/debug_websockets/36.jpg

6. Postman

截至目前,Postman 对 WebSockets 的支持仍处于测试阶段。 但是,我们仍然可以使用它来调试 WebSocket:

打开 Postman 并按 Ctrl + NNewWebSocket Request

/uploads/debug_websockets/38.jpg

接下来,在 Enter Server URL 文本框中,输入 WebSocket URL 并单击 Connect

/uploads/debug_websockets/40.jpg

6.1. 握手

连接成功后,在 Messages 部分,单击连接请求以查看握手详细信息:

/uploads/debug_websockets/42.jpg

6.2. 消息交换

现在,让我们检查一下客户端和服务器之间的消息交换:

/uploads/debug_websockets/44.jpg

一旦客户端订阅了该主题,我们就可以看到客户端和服务器之间的消息流。

6.3. 连接终止

此外,让我们看看如何调试客户端和服务器的连接终止。 首先,点击Postman中的Disconnect按钮,从客户端关闭连接:

/uploads/debug_websockets/46.jpg

同样,要检查服务器连接终止,请关闭服务器:

/uploads/debug_websockets/48.jpg

7. Spring WebSocket Client

最后,让我们使用基于 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 数据包

/uploads/debug_websockets/50.jpg