如何正确关闭 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 连接的主要内容,如果未能解决你的问题,请参考以下文章
如何在Java-EE中使用hibernate实现ManyToMany关系?
如何正确分离 JavaScript 视图/逻辑代码 [关闭]
如何使用 java-ee8、microProfile 4.0、Openliberty 21 和 Docker 设置特定于阶段的微配置文件配置