接收请求并以netty发送响应

时间:2016-02-22 02:34:01

标签: netty

我有这样的服务器:

import 'jquery';
import 'datatables';

请求处理程序如下:

//...
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();
}

它完美无缺!

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

// (1)  ctx.write(obj);

或者只是发回请求:

// (2)   ctx.write(response);

它不起作用!我不会在客户端看到这个回复。

这里有什么问题? 什么是阅读消息的正确方法,做一些逻辑并向客户发送新的响应?

1 个答案:

答案 0 :(得分:3)

您的管道已在ChannelInitializer初始化,只有一个处理程序:您的requestHandler

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

然后当你调用write( object )(你应该调用writeAndFlush())时,参数将发送到要处理的管道。如果参数是ByteBuf,则数据将按预期写入通道连接。但如果没有,就像在你的情况下,对象是protobuf消息的一个实例,你需要一个出站处理程序进入管道,将这种对象转换为ByteBuf

Netty提供了一个Protobuf encoder/decoder handlers的实现,您可以在管道上添加该实现。但是你也可以扩展ChannelOutboundHandlerAdapter并用自己的方式来序列化protobuf消息。

在您的具体情况下,您的管道应该是:

  • 处理protobuf消息的出站处理程序,将其转换为ByteBuf并在管道上向下游发送
  • 一个处理ByteBuf的入站处理程序,将其转换为protobuf消息并在管道上游发送此消息
  • 处理protobuf消息并执行某些操作(如发送响应)的入站处理程序