WebSocket:永远不会调用 OnClose() [英] WebSocket: OnClose() is never called

查看:179
本文介绍了WebSocket:永远不会调用 OnClose()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 WebSocket 端点实现一个应用程序.这是一些代码:

I'm implementing an application with a WebSocket endpoint. Here is some code:

@ApplicationScoped
@ServerEndpoint(value="/socket", encoders = {MessageEncoder.class, CommandEncoder.class})
public class SocketEndpoint {

    /** Default-Logger */
    private final static Logger LOG = LoggerFactory.getLogger(SocketEndpoint.class);

    @Inject
    SessionHandler sessionHandler;

    @OnOpen
    public void open(Session session, EndpointConfig config) {
        LOG.debug("Connected session => '{}' - '{}'", session, config);
        sessionHandler.initSession(session);
    }

    @OnMessage
    public void onMessage(Session session, String messageJson) {
        // do something
    }

    @OnClose
    public void onClose(Session session, CloseReason reason) {
        LOG.debug("Closing session => '{}' - '{}'", session, reason);
        sessionHandler.removeSession(session);
    }

    @OnError
    public void onError(Session session, Throwable ex) { 
        LOG.error("WebSocket error => '{}'", ex.getMessage()); 
    }
}

其中一个编码类如下所示:

One of the encode class looks like this:

public class MessageEncoder implements Encoder.Text<Message> {

    /** Default-Logger */
    private final static Logger LOG = LoggerFactory.getLogger(MessageEncoder.class);

    @Override
    public void init(EndpointConfig config) {
        LOG.debug("Init MessageEncoder");
    }

    @Override
    public void destroy() {
        LOG.debug("Destroy MessageEncoder");
    }

    @Override
    public String encode(MessageE message) throws EncodeException {
        return message.toString();
    }
}

打开 WebSocket 会按预期调用 SocketEndpoint.open().关闭 WebSocket 只会调用 MessageEncoder.destroy() 而不是 SocketEndpoint.close().

Opening the WebSocket calls SocketEndpoint.open() as expected. Closing the WebSocket only calls MessageEncoder.destroy() but not SocketEndpoint.close().

谁能给我一个建议,我做错了什么?如果没有解决方案,我将不得不手动检查注册的会话是否仍然存在,因为 MessageEncoder.destroy() 没有参数.

Can anyone give me an advise, what I did wrong? Without a solution I would have to check manually if registered sessions are still alive since MessageEncoder.destroy() has no parameters.

提前致谢!

更新

刚刚实现了一个虚拟端点:

Just implemented a dummy endpoint:

@ApplicationScoped
@ServerEndpoint("/dummy")
public class DummyEndpoint {

    /** Default-Logger */
    private final static Logger LOG = LoggerFactory.getLogger(DummyEndpoint.class);

    @OnOpen
    public void open(Session session, EndpointConfig config) {
        LOG.debug("Connected session with principal => '{}'", session.getId());
    }

    @OnMessage
    public void onMessage(Session session, String messageJson) {
        LOG.debug("on message => '{}' => '{}'", session.getId(), messageJson); 
    }

    @OnClose
    public void onClose(Session session, CloseReason reason) {
        LOG.debug("Closing session => '{}' - '{}'", session, reason);
    }

    @OnError
    public void onError(Session session, Throwable ex) { 
        LOG.error("WebSocket error => '{}' => '{}'", session, ex.getMessage()); 
    }
}

当使用这个虚拟端点时 @OnClose 被正确调用.我只能看到 SocketEndpoint 类的一个主要区别:DummyEndpoint 不使用任何 Encoder 类.

When using this dummy endpoint @OnClose is properly called. I can only see one major difference to the SocketEndpoint class: DummyEndpoint does not use any Encoder classes.

有什么提示吗?

推荐答案

正如评论中提到的,代码运行得很好.如果我们从这个wildfly-websocket-quickstart开始,添加@OnCloseServerEndpoint 上装饰的方法,它在使用 Wildfly 10.x 和最近的浏览器(例如 Chrome v59.x)时可以正常工作.ServerEndpoint 在这里工作的一个例子(使用 @Inject 不要忘记在 WEB-INF 文件夹中添加一个 beans.xml):

As mentioned in the comments, the code is working just fine. If we start from this wildfly-websocket-quickstart, adding an @OnClose decorated method on the ServerEndpoint, it works fine using Wildfly 10.x, and recent browsers (for instance Chrome v59.x). An example of ServerEndpoint working here (to use @Inject don't forget to add a beans.xml in WEB-INF folder):

@ApplicationScoped
@ServerEndpoint(value="/shout", encoders = {MessageEncoder.class})
public class ShoutServerEndpoint {

    @Inject
    SessionHandler s;

    @OnOpen
    public void open(Session session, EndpointConfig config) throws Exception {
        s.initSession(session);
    }

    @OnMessage
    public void shout(String text, Session client) {
        System.out.println("Session: " + client + " has text: " + text);
        Message m = new Message();
        try {
            client.getBasicRemote().sendObject(m);//use the encoder to write some dummy message
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (EncodeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        client.getAsyncRemote().sendText(text.toUpperCase());
    }


    @OnClose
    public void onClose(Session client, CloseReason reason){
        System.out.println("Session " + client + " closing for " + reason);
        s.destroySession(client);

    }

    @OnError
    public void onError(Session session, Throwable ex) { 
        System.out.println("error: " + ex.getMessage() );
    }
}

因此,罪魁祸首似乎是在重新部署 web 应用程序期间没有清理 wildfly 使用的旧版本代码,例如,使用 Eclipse,在出现奇怪行为的情况下值得使用 <使用的服务器上的 code>Clean 选项(请参阅:这个 Eclipse 文档)

Thus the culprit seems to be that there is an older version of the code used by wildfly that was not cleaned during a redeployment of the webapp, for instance, using Eclipse, it is worth in case of strange behavior to use the Clean option on the server used (see: this Eclipse doc)

如果直接使用 wildfly 部署,您可以通过删除所有内容来清理资源(来自 这篇文章):

If deploying directly with wildfly, you can clean your resources by deleting everything in (from this article):

  • /[wildfly-location]/standalone/data
  • /[wildfly-location]/standalone/deployments
  • /[wildfly-location]/standalone/tmp

它确保在未来部署期间不会保留您的代码的旧副本.

It ensures no older copies of your code remains during a future deployment.

这篇关于WebSocket:永远不会调用 OnClose()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆