在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',一切都像个符咒!谢谢