java - 在 Netty 4.x 中服务器没有实现客户端发送的消息
问题描述
我尝试通过简单地实现以下示例来学习 Netty 4.x。我有一个服务器和一个客户端。在某个时间点,客户端想知道当前的日期时间,他会询问服务器“现在几点?”。当服务器意识到这个问题时,他会用当前的日期时间回复。
我的实现如下
TimeClientInboundHandler.java
public class TimeClientInboundHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
try {
long currentTimeMillis = (byteBuf.readUnsignedInt() - 2208988800L) * 1000L;
System.out.println(new Date(currentTimeMillis));
ctx.close();
} finally {
byteBuf.release();
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.write("What time is it?");
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
TimeServerInboundHandler.java
public class TimeServerInboundHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
try {
byteBuf.readCharSequence(1024, StandardCharsets.UTF_8);
System.out.println(byteBuf.toString());
} finally {
((ByteBuf) msg).release();
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
final ByteBuf byteBuf = ctx.alloc().buffer(4);
byteBuf.writeInt((int) (System.currentTimeMillis() / 1000L + 2208988800L));
final ChannelFuture f = ctx.writeAndFlush(byteBuf);
f.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
assert f == future;
ctx.close();
}
});
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
但是,我没有得到预期的结果。具体来说,在服务器端,问题“现在几点?” 尚未在控制台上打印出来。
我实施了什么错误?
解决方案
原因
这个问题有两个原因。
服务器端无法实现从客户端发送的消息,因为消息(从客户端)以错误的方式写入。而不是ctx.write("What time is it?");
,我们应该实现如下ctx.write(Unpooled.coppiedBuffer("What time is it?", StandardCharsets.UTF_8);
此外,在 中TimeServerInboundHandler.java
,我们应该删除方法channelActive()
。这是因为channelRead()
永远不会触发,但当然channelActive()
是在通道处于活动状态时。
解决方案
TimeClientInboundHandler.java
public class TimeClientInboundHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf byteBuf = (ByteBuf) msg;
try {
System.out.println("Client received: " + byteBuf.toString(StandardCharsets.UTF_8));
ctx.close();
} finally {
byteBuf.release();
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.copiedBuffer("What time is it?", StandardCharsets.UTF_8));
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
TimeServerInboundHandler.java
public class TimeServerInboundHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf byteBuf = (ByteBuf) msg;
try {
System.out.println("Server received: " + byteBuf.toString(StandardCharsets.UTF_8));
String answer = Utils.getCurrentTime();
ctx.writeAndFlush(Unpooled.copiedBuffer(answer, StandardCharsets.UTF_8));
} finally {
((ByteBuf) msg).release();
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
Utils.java
public class Utils {
public static String getCurrentTime() {
long currentTimeMillis = ((System.currentTimeMillis() / 1000L + 2208988800L) - 2208988800L) * 1000L;
return new Date(currentTimeMillis).toString();
}
}
推荐阅读
- ruby-on-rails - 在 lib/file.rb 中使用 ApplicationHelper
- julia - 使用符号作为访问器的正确方法
- css - SVG 作为 CSS 背景 - 有没有办法重复-x,中间没有空格?
- google-cloud-platform - 如何在不向公众公开的情况下测试在 Compute Engine 实例上运行的 HTTP 服务器?
- python - 如何使图像向鼠标单击方向移动?
- dns - 在 openwrt uci 命令行中更改 DNS 设置
- javascript - 选择具有相同值的无线电输入时如何禁用具有某些值的无线电输入
- jenkins - 使用 generic-webhook-trigger 插件时,如何在 Job DSL 脚本中创建多个 genericVariables?
- python-3.x - 打印 .csv 文件的最后 3 行
- ios - 你如何自动布局约束按钮内的通知标签?