简体   繁体   English

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

[英]How to close java-ee websocket connection properly

I am implementing a small chat application using java-ee websockets. 我正在使用java-ee websockets实现一个小型聊天应用程序。
At one time I want to close session for a client for various reasons so for closing connection. 有一次,我想出于各种原因关闭客户端的会话,以便关闭连接。
For closing connection I called onClose function and in that function I called session.close() But after that I got the following error: 为了关闭连接,我调用了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)

I'm not sure what I did wrong and I why I got this exception. 我不确定我做错了什么,为什么我得到了这个例外。

I was having the same issue as I started learning this stuff today. 我今天开始学习这些东西时遇到了同样的问题。

What I have found so far is that on the server at the annotation @OnMessage I was closing the connection when the Server received a "quit" message by calling the session.close. 到目前为止我发现的是,在注释@OnMessage的服务器上,当服务器通过调用session.close收到“退出”消息时,我正在关闭连接。 Then at the end of the @OnMessage I was issuing the return that is mandatory as the method requires a return and it was the return that was throwing the Exception since the session has been closed already. 然后在@OnMessage结束时,我发出了强制性的返回,因为该方法需要返回,并且它是抛出异常的返回,因为会话已经关闭。

My solution is to instead of making the server close the session I send a message "youquit" back to the client and I have the client calling the session.close. 我的解决方案是,不是让服务器关闭会话,而是将“youquit”消息发送回客户端,我让客户端调用session.close。

The server now receives the close event and is ready for the next connection and the client ends without exception. 服务器现在接收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));
}

I have tried to catch the exception at the return level but it does not work. 我试图在返回级别捕获异常,但它不起作用。

I now believe that you cannot close the connection at the @OnMessage entry point. 我现在相信你无法在@OnMessage入口点关闭连接。

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

Websocket OnClose method invokes when session closes, you dont need close session. Websocket OnClose方法在会话关闭时调用,您不需要关闭会话。 You want close closed session. 你想要关闭闭会话。 This error shows that session already closed. 此错误显示会话已关闭。 You can see it from here: 你可以从这里看到它:

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

Once the session is closed, it is no longer valid for use by applications. 会话关闭后,它不再适用于应用程序。 Calling any of its methods (with the exception of the close() methods) once the session has been closed will result in an IllegalStateException being thrown. 一旦会话关闭,调用其任何方法(close()方法除外)将导致抛出IllegalStateException。 Developers should retrieve any information from the session during the Endpoint.onClose(javax.websocket.Session, javax.websocket.CloseReason) method. 开发人员应在Endpoint.onClose(javax.websocket.Session,javax.websocket.CloseReason)方法期间从会话中检索任何信息。 Following the convention of Closeable calling the Session close() methods after the Session has been closed has no effect. 遵循Closeable约定,在Session关闭后调用Session close()方法没有任何效果。

Check if the session is open and close it if yes. 检查会话是否打开,如果是,则关闭会话。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM