在netty中接收请求并发送响应

在netty中接收请求并发送响应,netty,Netty,我有这样的服务器: //... ServerBootstrap networkServer = new ServerBootstrap(); networkServer .group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 128) .handler(new LoggingHandler(LogLevel.TRACE)) .

我有这样的服务器:

//...
ServerBootstrap networkServer = new ServerBootstrap();
networkServer
  .group(bossGroup, workerGroup)
  .channel(NioServerSocketChannel.class)
  .option(ChannelOption.SO_BACKLOG, 128)
  .handler(new LoggingHandler(LogLevel.TRACE))
  .childHandler(new ChannelInitializer<SocketChannel>() {
        @Override
        public void initChannel(SocketChannel channel) throws Exception {
          ChannelPipeline p = channel.pipeline();
          p.addLast(requestHandler);
        }
      });
// ...
@Sharable
@Component
public class RequestHandler extends ChannelInboundHandlerAdapter {

private static final Logger logger = LogManager.getLogger(RequestHandler.class);

@Override
public void channelRead(ChannelHandlerContext ctx, Object obj) {
  // (1)  ctx.write(obj);

  ByteBuf in = (ByteBuf) obj;
  byte[] out = new byte[in.readableBytes()];
  try {
    int i = 0;
    while (in.readableBytes() > 0) {
      out[i++] = in.readByte();
    }

    Sproto.SProto msg = Sproto.SProto.parseFrom(out);

    Sproto.SProto response = Sproto.SProto.newBuilder()
      .setStatusCode(Common.ConfirmCodeStatus.OK)
      .setConnectResponse(Player.ConnectResponse.newBuilder())
      .build();

  // (2)   ctx.write(response);
  // (3)   ctx.write(obj);
  } catch (Exception ex) {
    logger.error(ex.getMessage(), ex);
  }
}

@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
  ctx.flush();
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
  logger.error(cause.getMessage(), cause);
  ctx.close();
}
当我通过以下方式发回请求时:

// (1)  ctx.write(obj);
它工作得很好

但当我试图在解析请求后发送protobuf响应时:

// (2)   ctx.write(response);
或者只发送回请求:

// (3)   ctx.write(obj);
它不起作用!我在客户端看不到这种反应

这里怎么了?
阅读消息、执行一些逻辑并向客户端发送新响应的正确方法是什么?

您的管道在
通道初始值设定项中初始化,只有一个处理程序:您的
请求处理程序

此通道是具有任何定义类型的
ChannelInboundHandlerAdapter
,因此它处理
对象
类型。因此,当收到数据包(
ByteBuf
)时,您的处理程序将被正确调用

然后,当您调用
write(object)
(您可能应该调用
writeAndFlush()
)时,参数被发送到要处理的管道。如果参数是ByteBuf
,数据将按预期写入通道连接。但如果不是,就像在您的例子中,对象是protobuf消息的实例一样,您需要一个出站处理程序到管道中,以将此类对象转换为
ByteBuf

Netty提供了一个可添加到管道中的实现。但您也可以扩展和编写自己的方式来序列化protobuf消息

在您的特定情况下,您的管道应该类似于:

  • 一个外边界处理程序,它处理protobuf消息,将其转换为ByteBuf并通过管道将其发送到下游
  • 一个内绑定处理程序,它处理ByteBuf,将其转换为protobuf消息,并通过管道向上游发送该消息
  • 一个入站处理程序,处理protobuf消息并执行一些操作(如发送响应)

您的管道在
通道初始值设定项中初始化,只有一个处理程序:您的
requestHandler

此通道是具有任何定义类型的
ChannelInboundHandlerAdapter
,因此它处理
对象
类型。因此,当收到数据包(
ByteBuf
)时,您的处理程序将被正确调用

然后,当您调用
write(object)
(您可能应该调用
writeAndFlush()
)时,参数被发送到要处理的管道。如果参数是ByteBuf
,数据将按预期写入通道连接。但如果不是,就像在您的例子中,对象是protobuf消息的实例一样,您需要一个出站处理程序到管道中,以将此类对象转换为
ByteBuf

Netty提供了一个可添加到管道中的实现。但您也可以扩展和编写自己的方式来序列化protobuf消息

在您的特定情况下,您的管道应该类似于:

  • 一个外边界处理程序,它处理protobuf消息,将其转换为ByteBuf并通过管道将其发送到下游
  • 一个内绑定处理程序,它处理ByteBuf,将其转换为protobuf消息,并通过管道向上游发送该消息
  • 一个入站处理程序,处理protobuf消息并执行一些操作(如发送响应)

Hmmm。。。看起来它可以工作,但当我在out-bound处理程序中转换响应并发送它(ctx.writeAndFlush(unmooled.copiedBuffer(proto.toByteArray()))时,我在客户端上看不到此响应。但当我停止服务器实例时,我会立即在客户端收到此响应。为什么?只要写最后一个字节'\n',一切都像个符咒!谢谢你。。。看起来它可以工作,但当我在out-bound处理程序中转换响应并发送它(ctx.writeAndFlush(unmooled.copiedBuffer(proto.toByteArray()))时,我在客户端上看不到此响应。但当我停止服务器实例时,我会立即在客户端收到此响应。为什么?只要写最后一个字节'\n',一切都像个符咒!谢谢