连接第二个客户端

时间:2017-12-06 20:52:20

标签: java websocket netty nio vert.x

我有简单的基于Vertx的websocket聊天应用程序。它由MsgServerVerticle和MsgClientVerticle两部分组成(下面的源代码)。所以,如果我实例化一个服务器而只有一个客户端,它看起来像是正常工作。第二个客户端连接后,服务器开始尝试将其通告给其他客户端。事情会很奇怪。 Log表示netty支持编码 - 解码websocket帧连续循环。我正在使用的帧类型,二进制或文本没有区别,问题是相同的。 log screenshot here

出了什么问题?

MsgClientVerticle源代码:

private Logger L;

private String eBusTag;
private String backwardTag;
private String targetHost;
private int port;
private String id;
private String path;

private EventBus eBus;

private HttpClient client;

public MsgClientVerticle(String eBusTag, String targetHost, int port, String path, String id, String backwardTag) {
    this.eBusTag = eBusTag;
    this.targetHost = targetHost;
    this.path = path;
    this.port = port;
    this.id = id;
    this.backwardTag = backwardTag;

    L = LoggerFactory.getLogger(eBusTag);
}

@Override
public void start(Future<Void> startFuture) throws Exception {
    L.info("Initializing client connection to " + targetHost + ":" + port + path);
    eBus = vertx.eventBus();

    try {


        client = vertx.createHttpClient();

        client.websocket(port, targetHost, path, webSock -> {
            L.info("Connected to " + targetHost + ":" + port + "/" + path);
            eBus.publish(backwardTag, Utils.msg("Connected"));
            webSock.binaryMessageHandler(buf -> {
                eBus.publish(backwardTag, Utils.bufToJson(buf));
            });
            eBus.consumer(eBusTag).handler(msg -> {
                JsonObject message = (JsonObject) msg.body();
                webSock.writeBinaryMessage(Utils.jsonToBuf(message));
            });
        });
    } catch (NullPointerException e) {
        L.error("Null Pointer: " + e.getLocalizedMessage());
        e.printStackTrace();
    }


    startFuture.complete();
}

@Override
public void stop(Future<Void> stopFuture) throws Exception {
    L.info("Connection to " + targetHost + ":" + port + "/" + path + " closed");
    client.close();
    stopFuture.complete();
}

和MsgServerVerticle来源:

private Logger L;

private String path;
private int port;
private String eBusTag;
private String backwardTag;

private HttpServer server;

private EventBus eBus;

private Set<ServerWebSocket> conns;

public MsgServerVerticle(int port, String eBusTag, String backwardTag) {
    this.port = port;
    this.eBusTag = eBusTag;
    this.backwardTag = backwardTag;

    conns = new ConcurrentSet<>();
    path = eBusTag;

    L = LoggerFactory.getLogger(eBusTag);

}

@Override
public void start(Future<Void> startFuture) throws Exception {
    eBus = vertx.eventBus();
    L.info("Initializing server instance at port " + port);

    server = vertx.createHttpServer();

    server.websocketHandler(webSock -> {

        if (!webSock.path().equals(path)) {

            webSock.reject();

        } else {

            conns.add(webSock);

            conns.forEach(sock -> {
                if (sock != webSock) {
                    sock.writeBinaryMessage(Utils.jsonToBuf(Utils.msg("SERVER: new client " + webSock.remoteAddress().toString())));
                }
            });

            eBus.publish(backwardTag, Utils.msg("SERVER: new client " + webSock.remoteAddress().toString()));

            webSock.binaryMessageHandler(buf -> {
                JsonObject msg = Utils.bufToJson(buf);
                conns.forEach(sock -> {
                    if (sock != webSock) {
                        sock.writeBinaryMessage(buf);
                    }
                });
                eBus.publish(backwardTag, msg);
            });

        }

    });

    server.listen(port);

    startFuture.complete();
}

@Override
public void stop(Future<Void> stopFuture) throws Exception {
    conns.forEach(sock -> {
        sock.writeFinalTextFrame("Server is shutting down...");
    });
    server.close();
    stopFuture.complete();
}

1 个答案:

答案 0 :(得分:0)

我无法重现原始问题。但是我必须首先做一些改变来测试它。

服务器初始化的一个变化是:

this.path = "/" + eBusTag;

否则此检查将始终失败:

if (!webSock.path().equals(this.path)) {

由于websock.path()始终以/开头,因此/anything = / = anything

其次,请查看我如何初始化客户端,并检查您是否也这样做:

    final Vertx vertx = Vertx.vertx();

    vertx.deployVerticle(new MsgServerVerticle(8080,
            "ebus",
            "back"), new DeploymentOptions().setWorker(true), (r) -> {
        vertx.deployVerticle(new MsgClientVerticle("ebus",
                "127.0.0.1",
                8080,
                "/ebus",
                "a",
                "back"), new DeploymentOptions().setWorker(true), (r2) -> {
            vertx.deployVerticle(new MsgClientVerticle("ebus",
                    "127.0.0.1",
                    8080,
                    "/ebus",
                    "b",
                    "back"), new DeploymentOptions().setWorker(true), (r3) -> {
                System.out.println("Done");
            });
        });
    });

第三,据我所知,您的Utils类是您实现的。我的实现如下:

public class Utils {
    public static Buffer jsonToBuf(final JsonObject message) {
        return message.toBuffer();
    }

    public static JsonObject bufToJson(final Buffer buf) {
        return buf.toJsonObject();
    }

    public static JsonObject msg(final String msg) {
        return new JsonObject("{\"value\":\"" + msg + "\"}");
    }
}

希望这有助于查明您的问题。