我想在Netty nio中创建一个具有两个客户端和一个服务器的通信系统。更具体地说,首先,我希望当两个客户端与服务器连接时从服务器发送一条消息,然后在这两个客户端之间交换数据。我正在使用code provided from this example。我对代码的修改可以在这里找到:link
当第一个客户端连接时,serverHandler中的channelRead似乎可以正常工作,因此它始终返回1,但是当连接第二个客户端时,它不会更改为2。当两个客户端都连接到服务器时,如何从服务器正确检查?如何从客户端的主要功能动态读取此值?那么,让两个客户交流的最佳方法是什么?
编辑1:显然,客户端服务正在运行并直接关闭,因此每次我运行新的NettyClient时都已连接,但此后该连接已关闭。因此,计数器始终从零到1变动。正如我在以下评论中所建议的那样,我在同一端口上使用telnet对其进行了测试,但是计数器似乎正常增加,但是使用NettyClient服务没有。
编辑2:似乎我遇到的问题来自future.addListener(ChannelFutureListener.CLOSE);
中channelRead
中的ProcessingHandler class
。当我发表评论时,代码似乎可以正常工作。但是,不确定将其注释掉会带来什么后果。此外,我想从客户端的主要功能中检查返回消息何时是特定的两个。我该如何创建一种方法来等待服务器发出特定消息,同时又阻止主要功能。
static EventLoopGroup workerGroup = new NioEventLoopGroup();
static Promise<Object> promise = workerGroup.next().newPromise();
public static void callClient() throws Exception {
String host = "localhost";
int port = 8080;
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new RequestDataEncoder(), new ResponseDataDecoder(), new ClientHandler(promise));
}
});
ChannelFuture f = b.connect(host, port).sync();
} finally {
//workerGroup.shutdownGracefully();
}
}
我希望在main函数内部调用该方法并返回结果,并在结果为2时继续使用main函数。但是,我无法在一段时间内调用callClient,因为它将在同一个客户端上运行多次。
callBack();
while (true) {
Object msg = promise.get();
System.out.println("Case1: the connected clients is not two");
int ret = Integer.parseInt(msg.toString());
if (ret == 2){
break;
}
}
System.out.println("Case2: the connected clients is two");
// proceed with the main functionality
如何为第一个客户端更新promise变量。当我运行两个客户端时,对于第一个客户端,我总是收到以下消息:
似乎 promise 没有正常更新,而对于第二个客户,我总是收到:
最佳答案
如果我的内存正确,则ChannelHandlerContext每个 channel 一个,并且它的管道中可以有多个ChannelHandlers。您的channel变量是处理程序类的实例变量。然后为每个连接创建一个新的ProcessingHandler实例。因此,一旦初始化,每个人在channels
变量中将只有一个连接-它是为它创建的。
请参阅服务器代码(NettyServer.java)中initChannel函数中的new ProcessingHandler()
。
您可以将channels
变量设为静态,以便在ProcessingHandler实例之间共享它。或者,您可以在其他地方创建单个ProcessingHandler实例(例如,作为run()
函数中的局部变量),然后将该实例传递给addLast
调用而不是new ProcessingHandler()
。