如何正确关闭 java-ee websocket 连接

Posted

技术标签:

【中文标题】如何正确关闭 java-ee websocket 连接【英文标题】:How to close java-ee websocket connection properly 【发布时间】:2014-10-25 01:08:59 【问题描述】:

我正在使用 java-ee websockets 实现一个小型聊天应用程序。 有一次,出于各种原因,我想关闭客户端的会话,以便关闭连接。 为了关闭连接,我调用了onClose 函数,在该函数中我调用了session.close() 但之后出现以下错误:

java.lang.IllegalStateException: The WebSocket session has been closed and no method (apart from close()) may be called on a closed session
    at org.apache.tomcat.websocket.WsSession.checkState(WsSession.java:643)
    at org.apache.tomcat.websocket.WsSession.addMessageHandler(WsSession.java:168)
    at org.apache.tomcat.websocket.pojo.PojoEndpointBase.doOnOpen(PojoEndpointBase.java:81)
    at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:70)
    at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:129)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:629)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

我不确定我做错了什么以及为什么会出现这个异常。

【问题讨论】:

已经一年了..您是否弄清楚问题出在哪里以及如何正确处理?我现在在 Tomcat7 上遇到了同样的问题 【参考方案1】:

我今天开始学习这些东西时遇到了同样的问题。

到目前为止,我发现在服务器上的注释@OnMessage 上,当服务器通过调用 session.close 收到“退出”消息时,我正在关闭连接。 然后在 @OnMessage 结束时,我发出了强制返回,因为该方法需要返回,并且由于会话已经关闭,所以返回抛出异常。

我的解决方案不是让服务器关闭会话,而是向客户端发送一条消息“youquit”,然后让客户端调用 session.close。

服务器现在接收到关闭事件并准备好进行下一次连接,客户端无异常结束。

@OnMessage
public String onMessage(String message, Session session) throws DeploymentException, IOException 
    switch (message) 
        case "quit":
            //session.close(new CloseReason(CloseCodes.NORMAL_CLOSURE, "Game ended"));
            message = "you" + message;
            break;
    
    return message;


@OnClose
public void onClose(Session session, CloseReason closeReason) 
    logger.info(String.format("Session %s closed because of %s", session.getId(), closeReason));

我尝试在返回级别捕获异常,但它不起作用。

我现在认为您无法在 @OnMessage 入口点关闭连接。

【讨论】:

【参考方案2】:

这似乎是由于一个现已修复的错误造成的: https://github.com/Atmosphere/atmosphere/issues/1770

【讨论】:

我认为这与这种情况无关。 OP 似乎直接使用 JSR356 websocket API,而不是通过 Atmosphere 框架。【参考方案3】:

Websocket OnClose 方法在会话关闭时调用,您不需要关闭会话。你想要关闭封闭的会话。此错误表明该会话已关闭。你可以从这里看到它:

http://docs.oracle.com/javaee/7/api/javax/websocket/Session.html

一旦会话关闭,它就不再有效,供以下用户使用 应用程序。调用它的任何方法(除了 close() 方法)一旦会话被关闭将导致 抛出 IllegalStateException。开发人员应检索任何 会议期间的信息 Endpoint.onClose(javax.websocket.Session, javax.websocket.CloseReason) 方法。遵循 Closeable 调用 Session 的约定 Session 关闭后的 close() 方法无效。

【讨论】:

正如块引用所说的“在会话关闭后调用其任何方法(close() 方法除外)将导致抛出 IllegalStateException”但它正在抛出 IllegalStateException调用 session.close() 您确定在会话关闭后不调用其他方法吗?你调试过项目吗? 我要做的就是从服务器端强制关闭会话,这就是我调用 session.close() 的原因 当客户端被中断时,服务器上没有 OnClose 触发器,至少 Tomcat 9 可能还有很多其他的。如果客户端结束连接,则会引发 EndOfFile 错误。我在 OnError 中捕获并关闭了那里的连接。【参考方案4】:

检查会话是否打开,如果是则关闭它。

if(session.isOpen())
    session.close();

【讨论】:

以上是关于如何正确关闭 java-ee websocket 连接的主要内容,如果未能解决你的问题,请参考以下文章

IOCP怎么正确关闭socket

IOCP怎么正确关闭socket

如何在Java-EE中使用hibernate实现ManyToMany关系?

如何正确分离 JavaScript 视图/逻辑代码 [关闭]

如何使用 java-ee8、microProfile 4.0、Openliberty 21 和 Docker 设置特定于阶段的微配置文件配置

WebSockets,如何实现 ping?