我有简单的基于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();
}
答案 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 + "\"}");
}
}
希望这有助于查明您的问题。