NutzCN Logo
问答 websocket插件客户端连接之后直接断开
发布于 2295天前 作者 Marveliu 5149 次浏览 复制 上一个帖子 下一个帖子
标签:

nutzwk4.0项目中引用nutz-websokcet,在pom中引入了两个依赖,

浏览器端

    // 首先,需要创建一个WebSocket连接
    var ws;
    var WS_URL = window.location.host + "${base!}"+"/websocket"
    // 如果页面是https,那么必须走wss协议, 否则走ws协议
    if (location.protocol == 'http:') {
        ws = new WebSocket("ws://"+WS_URL);
    } else {
        ws = new WebSocket("wss://"+WS_URL);
    }
    // 连接成功后,会触发onopen回调
    ws.onopen = function(event) {
        console.log("websocket onopen ...");
        // 加入home房间
        ws.send(JSON.stringify({room:'home',"action":"join"}));
    };


    // 收到服务器发来的信息时触发的回调
    ws.onmessage = function(event) {
        console.log("websocket onmessage", event.data);
        var re = JSON.parse(event.data);
        if (re.action == "notify") {
            // 弹个浏览器通知
        } else if (re.action == "msg") {
            // 插入到聊天记录中
        }
    };

    ws.onclose = function(evt) {
        console.log("Connection closed.");
    };

    // 定时发个空消息,避免服务器断开连接
    function ws_ping() {
        if (ws) {
            ws.send("{}"); // TODO 断线重连.
        }
    }
    setInterval("ws_ping()", 25000); // 25秒一次就可以了

后台

@ServerEndpoint(value = "/websocket", configurator=NutWsConfigurator.class)
@IocBean // 使用NutWsConfigurator的必备条件
public class GybWebsocket extends AbstractWsEndpoint {
    // 并不需要你马上实现任何方法,它也马上能工作
}

浏览器console,也没有报错,就是连接了之后立刻断开。

websocket onopen ...
Connection closed.
WebSocket is already in CLOSING or CLOSED state.

debug了一下:
在AbstractWsEndpoint,貌似除了一些问题

    public void onOpen(Session session, EndpointConfig config) {
        this.changeSessionId(session);
        String wsid = session.getId();
        WsHandler handler = this.createHandler(session, config);
        handler.setRoomProvider(this.roomProvider);
        handler.setSession(session);
        handler.setHttpSession((HttpSession)config.getUserProperties().get("HttpSession"));
        handler.setEndpoint(this);
        handler.init();
        session.addMessageHandler(handler);
        this.sessions.put(wsid, session);     //断点无法运行到这里...
        this.handlers.put(wsid, handler);
    }

日志:websocket就只有这一句

[DEBUG] 2018-01-06 17:49:45,370 org.nutz.mvc.impl.UrlMappingImpl.get(UrlMappingImpl.java:110) - Search mapping for [GET] path=/websocket : NOT Action match
[DEBUG] 2018-01-06 17:49:45,374 org.nutz.ioc.impl.NutIoc.get(NutIoc.java:157) - Get 'gybWebsocket'<class cn.wizzer.app.web.commons.websocket.GybWebsocket>

然后我试了一下原生的websocketapi,没毛病...

@ServerEndpoint(value = "/websocket1")
public class TestWs {
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        System.out.print(1);
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
    }
}

希望大佬能指点一下~,谢谢

13 回复

可能是抛异常了,try catch看看

是undertow吗?

因为直接进去了AbstractWsEndpoint里面,这个类是jar包里面的class,我无法修改..
然后在idea中debug看到了,确实报错了。

onOpen()方法里面的session.addMessageHandler(handler);

java.lang.reflect.InvocationTargetException
java.lang.IllegalStateException: A text message handler has already been configured

然后就直接跳转到了onClose()

你的endpoint完整贴一下,启动报错那个代码

package cn.wizzer.app.web.commons.websocket;

import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.plugins.mvc.websocket.AbstractWsEndpoint;
import org.nutz.plugins.mvc.websocket.NutWsConfigurator;
import javax.websocket.server.ServerEndpoint;



// ServerEndpoint是websocket的必备注解, value是映射路径, configurator是配置类.
@ServerEndpoint(value = "/websocket", configurator=NutWsConfigurator.class)
@IocBean // 使用NutWsConfigurator的必备条件
public class GybWebsocket extends AbstractWsEndpoint {
}

额,那么神奇的? 报错信息完整贴一下,顺便告知一下容器版本

哦. 给不了报错,对吧?

是的...我使用的tomcat8

tomcat具体什么版本

一般15分钟~20分钟出快照版

我在我的endpoint加了一下onOpen,抛出错误之后貌似能用了..

// ServerEndpoint是websocket的必备注解, value是映射路径, configurator是配置类.
@ServerEndpoint(value = "/websocket", configurator=NutWsConfigurator.class)
@IocBean // 使用NutWsConfigurator的必备条件
public class GybWebsocket extends AbstractWsEndpoint {

    private static final Log log = Logs.get();

    public void onOpen(Session session, EndpointConfig config) {
        this.changeSessionId(session);
        String wsid = session.getId();
        WsHandler handler = this.createHandler(session, config);
        handler.setRoomProvider(this.roomProvider);
        handler.setSession(session);
        handler.setHttpSession((HttpSession)config.getUserProperties().get("HttpSession"));
        handler.setEndpoint(this);
        handler.init();
        try{
            session.addMessageHandler(handler);
        }catch (Exception e){
            log.debug(e);
        }

        this.sessions.put(wsid, session);
        this.handlers.put(wsid, handler);
    }
}
[DEBUG] 2018-01-06 19:01:31,241 cn.wizzer.app.web.commons.websocket.GybWebsocket.onOpen(GybWebsocket.java:36) - A text message handler has already been configured
java.lang.IllegalStateException: A text message handler has already been configured
	at org.apache.tomcat.websocket.WsSession.doAddMessageHandler(WsSession.java:248)
	at org.apache.tomcat.websocket.WsSession.addMessageHandler(WsSession.java:209)
	at cn.wizzer.app.web.commons.websocket.GybWebsocket.onOpen(GybWebsocket.java:34)
	at org.nutz.plugins.mvc.websocket.AbstractWsEndpoint._onOpen(AbstractWsEndpoint.java:87)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.tomcat.websocket.pojo.PojoEndpointBase.doOnOpen(PojoEndpointBase.java:66)
	at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:70)
	at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:127)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:703)
	at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2508)
	at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2497)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
[DEBUG] 2018-01-06 19:01:31,269 org.nutz.plugins.mvc.websocket.handler.AbstractWsHandler.join(AbstractWsHandler.java:50) - session(id=r7l14fvkp2gmgqfffrfo3aqla4) join room(name=wsroom:home)

好的,tomcat8.0.36 谢谢大佬,辣么忙还帮我看代码!

能搞定就好

添加回复
请先登陆
回到顶部