使用netty4.x客户端接收较大数据量报文时发生的读取不完整bug修复记录

本文记录了一次在使用Netty4.x作为客户端时遇到的大数据量报文读取不完整的bug修复过程。当服务端发送的报文超过一定大小,Netty框架错误地调用了readComplete(),导致数据接收不全。解决方案是在ClientHandler中添加标记,通过判断标记来决定是否继续读取数据,从而解决了该问题。
摘要由CSDN通过智能技术生成

1、先说问题

背景:服务是运行在Linux上的安全网关提供的,TCP协议发送 通过二进制编码的xml字符串 报文,报文头的第一个字段是int类型的表示字节序标记,第二个字段是int类型的表示整个报文长度。

现象:数据量较小时完全可以正常收发报文,当服务端发送的报文数据量较大时(本例是将近600k)概率性出现接收数据直接调用readComplete()方法而没有走channelRead()

跟踪:跟踪代码发现出问题时context 的 read() 方法执行中读取到一百多k(有时两百多也可能三百多,总之是还没读取到全部数据)时某次读到的数据本应该是1024字节(填满默认分配的ByteBuf)却只读到了576字节;

    netty框架代码中判断如果当前读到的字节数小于ByteBuf的size则认为是读取完成,因此调用了readComplete()方法,出错。。。

解决方案:在ClientHandler类添加一个标记flag,用于是否正常读取数据判断。channelRead()方法正常调用则将其置为true;readComplete方法中添加一个判断只有当flag为true时关闭context否则继续调用ctx.read()。

2、再上核心代码

Client:

 1 ClientHandler clientHandler = new ClientHandler(this);
 2             bootstrap.group(eventLoop)
 3                     .channel(NioSocketChannel.class)
 4                     .option(ChannelOption.TCP_NODELAY, true)
 5                     .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
 6                     .option(ChannelOption.MAX_MESSAGES_PER_READ, Integer.MAX_VALUE)
 7                     .handler(new ClientChannelInitializer(clientHandler));
 8             
 9             ChannelFuture f = bootstrap.connect(host, port).sync();
10 
11             f.channel().closeFuture().sync();
 1 private class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
 2         private ClientHandler clientHandler;
 3 
 4         public ClientChannelInitializer(ClientHandler clientHandler) {
 5             this.clientHandler = clientHandler;
 6         }
 7 
 8         @Override
 9         protected 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值