java - 如何使用 Spring 5 Reactive WebSocket 检测断开连接的客户端

标签 java spring websocket spring-websocket spring-webflux

我设法使用 Spring 5 Reactive WebSocket 支持 ( Chapter 23.2.4 ) 创建了一个 WebSocketHandler。接收和发送一切正常。但是,我不知道如何检测客户端断开连接。当调试客户端断开连接时,它会在 HttpServerWSOperations 类(netty.http.server 包)的服务器端某处停止,它会在其中检测到 CloseWebSocketFrame.

对如何处理客户端断开连接有什么建议吗?

最佳答案

我在响应式 org.springframework.web.reactive.socket.WebSocketHandler 中实现了一个关闭事件处理程序,如下所示:

public Mono<Void> handle(final WebSocketSession session) {
    final String sessionId = session.getId();
    if(sessions.add(sessionId)) {  // add session id to set to keep a count of active sessions
        LOG.info("Starting WebSocket Session [{}]", sessionId);
        // Send the session id back to the client
        WebSocketMessage msg = session.textMessage(String.format("{\"session\":\"%s\"}", sessionId));
        // Register the outbound flux as the source of outbound messages
        final Flux<WebSocketMessage> outFlux = Flux.concat(Flux.just(msg), newMetricFlux.map(metric -> {
            LOG.info("Sending message to client [{}]: {}", sessionId, metric);
            return session.textMessage(metric);             
        }));
        // Subscribe to the inbound message flux
        session.receive().doFinally(sig -> {
            LOG.info("Terminating WebSocket Session (client side) sig: [{}], [{}]", sig.name(), sessionId);
            session.close();
            sessions.remove(sessionId);  // remove the stored session id
        }).subscribe(inMsg -> {
            LOG.info("Received inbound message from client [{}]: {}", sessionId, inMsg.getPayloadAsText());
        });
        return session.send(outFlux);
    }
    return Mono.empty();
}

newMetricFlux 字段是出站 websocket 消息的来源。 Hook 关闭事件的技巧是入站消息通量上的 doFinally。当 websocket 客户端关闭时,入站通量终止。

但是,出于某种原因,在 netty channel 关闭和执行 doFinally 回调之间有 1 分钟的延迟。还不确定为什么。

这是浏览器客户端连接并立即关闭的日志输出。请注意第 3 行和第 4 行之间的 60 秒延迟。

2017-08-03 11:15:41.177 DEBUG 28505 --- [ctor-http-nio-2] r.i.n.http.server.HttpServerOperations   : New http connection, requesting read
2017-08-03 11:15:41.294  INFO 28505 --- [ctor-http-nio-2] c.h.w.ws.NewMetricsWebSocketHandler      : Starting WebSocket Session [87fbe66]
2017-08-03 11:15:48.294 DEBUG 28505 --- [ctor-http-nio-2] r.i.n.http.server.HttpServerOperations   : CloseWebSocketFrame detected. Closing Websocket
2017-08-03 11:16:48.293  INFO 28505 --- [ctor-http-nio-2] c.h.w.ws.NewMetricsWebSocketHandler      : Terminating WebSocket Session (client side) sig: [ON_COMPLETE], [87fbe66]

更新:2017 年 10 月 13 日:

从 Spring 5 GA 开始,上面提到的延迟不存在,我观察到我的回调在客户端关闭后立即被调用。不确定这是在哪个版本中修复的,但正如我所说,它已在 5.0 GA 中修复。

关于java - 如何使用 Spring 5 Reactive WebSocket 检测断开连接的客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45038008/

相关文章:

javascript - websocket.send() 参数

java - 从固定选项卡中删除滑动操作

java - 使用 toString 方法和 foreach 循环打印对象时返回什么?

java - 通用抽象类的自定义 Jackson 反序列化

java - Spring 批处理 : Profiling a batch processing application

javascript - 如何从套接字迭代多个值

javascript - 将 WebSocket 放在 WebWorker 上有意义吗?

java - hibernate 条件 : Perform JOIN in Subquery/DetachedCriteria

java - 为什么我无法访问 protected 字段?

java - @Autowired 和实例化