netty4发送HttpRequest及HttpReponse太大的问题(半包)

netty是对socket的封装,底下走的TCP还是老一套,太大的HTTP包发送的时候是要被切分成好几段的,发送之后接收就变得很麻烦。网上有人提出多种解决方式,我自己试了试,结果如下:   

1.对于HttpRequest,有人提出在头部协商消息体长度。不要轻易相信呐,骚年们,这玩意儿就是一个坑,写上之后那个不睁眼的TCP照样剁碎了给发出去!此处红色警戒!

2.不用TCP剁碎了,自己剁碎了传过去。此方是否对症,没试验。

3.定长消息。自我感觉不适合HttpRequest及HttpReponse这类东西,所以没试。

4.其他,如设置发送缓冲和接收缓冲等,均不管用

所以,从几个坑里面爬出来之后,我隆重推出netty的解决方案:用HttpObjectAggregator!!!

首先,在客户端和服务端的channel下的pipeline启动之前加上

 <span style="white-space:pre">	</span>ch.pipeline().addLast("aggregator", new HttpObjectAggregator(1024*1024*64));
        ch.pipeline().addLast("chunkedWriter", new ChunkedWriteHandler());  
接收的时候就这样:

/**
	 	 * 读取传过来的消息,read request message from channel
	 	 */
	    @Override
	    public void channelRead(ChannelHandlerContext ctx, Object msg)
	            throws Exception {
	        if (msg instanceof DefaultHttpRequest) {
	            request = (DefaultHttpRequest) msg;
	        }
	        if (msg instanceof HttpContent) {
	            HttpContent content = (HttpContent) msg;
	            ByteBuf buf = content.content();
	            messageOfClient = buf.toString(io.netty.util.CharsetUtil.UTF_8);
	            if(messageOfClient!=null&&!messageOfClient.contentEquals("")&&!messageOfClient.contains("ping")){
		            messageToSend+= messageOfClient;
	            }else{
	            	System.out.println("channel的数目:"+ServerDataSyncServer.channels.size()+" channelGroupSize");
	            	System.out.println(ctx.channel().remoteAddress().toString());
	            }
	            buf.release();
	            if(content instanceof LastHttpContent){
	            	//此处对其他客户端的心跳包不予处理,因为服务端掉线之后会客户端会循环侦测连接,客户端断掉之后将服务端将不打印输出信息
	            	if(messageToSend.length()>12&&messageToSend.substring(0, 2).contentEquals("DB")){

			            //消息长度符合一定条件,则是需要向其他客户端发送的数据库消息,调用方法转发
		            	System.out.println("Server已读取数据库持久化信息,将开始向所有客户端发送");
		            	ServerDataSyncServer.channels.remove(ctx.channel());
		            	System.out.println("messageToSend   "+messageToSend );
		            	String messageContent = messageToSend;
		            	ServerDataSyncServerSendGroup.sendToAllChannel(messageContent);
		            	messageToSend = "";
		            }
	            }
	        }
	    }

当然,我的发送客户端是短连接,
ServerDataSyncServer.channels.remove(ctx.channel());
长连接的对这句可以直接忽略。

这样就可以了,netty接收到分段的大TCP包之后会自动组装成完整的HTTPrequest或者HttpResponse,然后逐个读取分段的消息体,最后一个是LastHttpContent类型,读到这个就算是整个包读完了,再做后续处理即可。

完毕

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烂泥稀云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值