我有这样的服务器:
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);
它不起作用!我不会在客户端看到这个回复。
这里有什么问题? 什么是阅读消息的正确方法,做一些逻辑并向客户发送新的响应?
答案 0 :(得分:3)
您的管道已在ChannelInitializer
初始化,只有一个处理程序:您的requestHandler
此频道是ChannelInboundHandlerAdapter
,具有任何已定义的类型,因此它处理Object
类型。因此,当收到数据包(ByteBuf
)时,会正确调用您的处理程序。
然后当你调用write( object )
(你应该调用writeAndFlush()
)时,参数将发送到要处理的管道。如果参数是ByteBuf
,则数据将按预期写入通道连接。但如果没有,就像在你的情况下,对象是protobuf消息的一个实例,你需要一个出站处理程序进入管道,将这种对象转换为ByteBuf
。
Netty提供了一个Protobuf encoder/decoder handlers的实现,您可以在管道上添加该实现。但是你也可以扩展ChannelOutboundHandlerAdapter
并用自己的方式来序列化protobuf消息。
在您的具体情况下,您的管道应该是: