Netty(4)客户端服务器在同一个TCP Session中通信
Netty (4) client server communication in the same TCP Session
我需要构建一个客户端来启动与服务器的 TCP 连接,并在响应时每 10 秒发送一次握手请求并从服务器获得响应。服务器将能够发送我的客户端需要阅读和执行的另一种类型的请求。我正在使用 netty 4.0.26.Final.
我已经构建了一个客户端和一个虚拟服务器,但我遇到了一个问题,这可能意味着我有不明白的地方。
我的客户:
String host = "localhost";
int port = 9884;
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new MyChannelPipeline());
// Start the client.
ChannelFuture f = b.connect(host, port).sync();
String line = "line";
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while (!line.equals("exit")) {
line = in.readLine();
if (line == null) {
break;
}
}
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
}
ChannelPipleline:
@Override
public void initChannel(Channel ch) throws Exception {
ChannelPipeline channelPipeline = ch.pipeline();
//Encodes every request send from the client to the server
channelPipeline.addLast("clientRequestEncoder", new ClientRequestEncoder());
//Implements channelActive and exceptionCaught
channelPipeline.addLast("initialRequestHandler", new InitialRequestHandler());
channelPipeline.addLast("byteArrayDecoder", new ByteArrayDecoder());
channelPipeline.addLast("serverResponseDecoder", new ServerResponseDecoder());
channelPipeline.addLast("serverRequestDecoder", new ServerRequestDecoder());
//Reads the responses from the client requests AND
//reads the inbound requests from the server - Implements channelRead
//and exceptionCaught
channelPipeline.addLast("myResponseHandler", new MyResponseHandler());
}
问题是当我刷新对服务器的响应时(在 MyResponseHandler 中)并且在 InitialRequestHandler 中捕获异常:
ERROR=java.lang.UnsupportedOperationException:unsupported message type: ServerResponse (expected: ByteBuf, FileRegion)
我不明白为什么在握手请求总是正确刷新时响应没有刷新回服务器。在 write 和 flush 中,我都使用了 ChannelFuture
和 onOperationComplete 这个监听器 f.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
在失败时被触发。
我可以在同一个管道中使用两个处理程序吗?这是不好的做法吗?此外,我应该如何触发由用户输入触发的注销事件?
我使用一个覆盖 channelActive 和 channelRead 的处理程序解决了这个问题,并且我正确地重新安排了编码器和解码器。我也这样解决了"unregister event triggered by user input":
String line = "line";
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
do {
logger.info("You typed: " + line + ". Please type 'exit' to terminate the program!");
line = in.readLine();
} while (!line.equals("exit"));
logger.info("You typed: " + line + ". Please wait until the application is successfully shutdown...");
f.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
myChannelPipeline.getMyClientHandler().sendDisconnectRequest(future);
}
});
在 sendDisconnectReqeust 中,我发送最终请求,当我得到最终响应时(在 MyHandler 的 channelRead 中),我在管道上调用断开连接:
ChannelPromise cp = new DefaultChannelPromise(ctx.channel());
ctx.channel().pipeline().disconnect(cp);
但是,我的客户从未收到过有关入站请求的其他问题。
我需要构建一个客户端来启动与服务器的 TCP 连接,并在响应时每 10 秒发送一次握手请求并从服务器获得响应。服务器将能够发送我的客户端需要阅读和执行的另一种类型的请求。我正在使用 netty 4.0.26.Final.
我已经构建了一个客户端和一个虚拟服务器,但我遇到了一个问题,这可能意味着我有不明白的地方。
我的客户:
String host = "localhost";
int port = 9884;
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new MyChannelPipeline());
// Start the client.
ChannelFuture f = b.connect(host, port).sync();
String line = "line";
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while (!line.equals("exit")) {
line = in.readLine();
if (line == null) {
break;
}
}
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
}
ChannelPipleline:
@Override
public void initChannel(Channel ch) throws Exception {
ChannelPipeline channelPipeline = ch.pipeline();
//Encodes every request send from the client to the server
channelPipeline.addLast("clientRequestEncoder", new ClientRequestEncoder());
//Implements channelActive and exceptionCaught
channelPipeline.addLast("initialRequestHandler", new InitialRequestHandler());
channelPipeline.addLast("byteArrayDecoder", new ByteArrayDecoder());
channelPipeline.addLast("serverResponseDecoder", new ServerResponseDecoder());
channelPipeline.addLast("serverRequestDecoder", new ServerRequestDecoder());
//Reads the responses from the client requests AND
//reads the inbound requests from the server - Implements channelRead
//and exceptionCaught
channelPipeline.addLast("myResponseHandler", new MyResponseHandler());
}
问题是当我刷新对服务器的响应时(在 MyResponseHandler 中)并且在 InitialRequestHandler 中捕获异常:
ERROR=java.lang.UnsupportedOperationException:unsupported message type: ServerResponse (expected: ByteBuf, FileRegion)
我不明白为什么在握手请求总是正确刷新时响应没有刷新回服务器。在 write 和 flush 中,我都使用了 ChannelFuture
和 onOperationComplete 这个监听器 f.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
在失败时被触发。
我可以在同一个管道中使用两个处理程序吗?这是不好的做法吗?此外,我应该如何触发由用户输入触发的注销事件?
我使用一个覆盖 channelActive 和 channelRead 的处理程序解决了这个问题,并且我正确地重新安排了编码器和解码器。我也这样解决了"unregister event triggered by user input":
String line = "line";
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
do {
logger.info("You typed: " + line + ". Please type 'exit' to terminate the program!");
line = in.readLine();
} while (!line.equals("exit"));
logger.info("You typed: " + line + ". Please wait until the application is successfully shutdown...");
f.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
myChannelPipeline.getMyClientHandler().sendDisconnectRequest(future);
}
});
在 sendDisconnectReqeust 中,我发送最终请求,当我得到最终响应时(在 MyHandler 的 channelRead 中),我在管道上调用断开连接:
ChannelPromise cp = new DefaultChannelPromise(ctx.channel());
ctx.channel().pipeline().disconnect(cp);
但是,我的客户从未收到过有关入站请求的其他问题。