



下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、使用Netty军决TCP粘包和拆包问题过程详解刖百我们介绍了如果使用Netty来开发一个简单的服务端和客户端,接下来我们来讨论如何使用解码器来解决TCP的粘包和拆包问题TCP为什么会粘包拆包我们知道,TCP是以一种流的方式来进行网络转播的,当t三次握手简历通信后,客户端服务端之间就建立了一种通讯管道,我们可以想象成自来水管道,流出来的水是连城一片的,是没有分界线的。TCP底层并不了解上层的业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分。所以对于我们应用层而言。我们直观是发送一个个连续完整TCP数据包的,而在底层就可能会出现将一个完整的TCP拆分成多个包发送或者将多个包封装成一个
2、大的数据包发送。这就是所谓的TCP粘包和拆包。当发生TCP粘包拆包会发生什么情况我们举一个简单例子说明:客户端向服务端发送两个数据包:第一个内容为;第二个内容为。服务端接受一个数据并做相应的业务处理(这里就是打印接受数据加一个逗号)。那么服务端输出结果将会出现下面四种情况服务端响应结果结论12,345,6正常接收,没有发生粘包和拆包4异常接收,发生t粘包24,异常接收,发生t拆包25异常接收,发生t拆包和粘包如何解决主流的协议解决方案可以归纳如下:消息定长,例如每个报文的大小固定为个字节,如果不够,空位补空格;在包尾增加回车换行符进行切割;将消息分为消息头和消息体,消息头中包含表示消息总长度的
3、字段;更复杂的应用层协议。对于之刖描述的案例,在这里我们就可以采取方案1和方案3。以方案为例:我们每次发送的TCP包只有三个数字,那么我将报文设置为个字节大小的,此时,服务器就会以三个字节为基准来接受包,以此来解决站包拆包问题。Netty的解决之道LineBasedFrameDecoder废话不多说直接上代码服务端Pteettt配置服务端的N线程组et三=newNioetworkerGroeNtyeetteServerBootsteeNServerSocketChannel.cltCetSO_BACKLOG,.childHandler(newChildChannelHandler();/绑定端
4、口,同步等待成功ChannelFuturef=b.bind(port).sync();/等待服务端监听端口关闭f.channel().closeFuture().sync();finally/优雅退出,释放线程池资源bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();privateclassChildChannelHandlerextendsChannelInitializerOverrideprotectedvoidinitChannel(SocketChannelarg0)throwsExceptionarg0.p
5、ipeline().addLast(newLineBasedFrameDecoder(1024);/1arg0.pipeline().addLast(newStringDecoder();/2arg0.pipeline().addLast(newPrintServerHandler();publicstaticvoidmain(Stringargs)throwsExceptionintport=8080;newTimeServer().bind(port);服务端HandlerpublicclassPrintServerHandlerextendsChannelHandlerAdapterOv
6、erridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg)throwsExceptionByteBufbuf=(ByteBuf)msg;bytereq=newbytebuf.readableBytes();buf.readBytes(req);将缓存区的字节数组复制到新建的req数组中Stringbody=newString(req,UTF-8);System.out.println(body);Stringresponse=打印成功;ByteBufresp=Unpooled.copiedBuffer(response.get
7、Bytes();ctx.write(resp);OverridepublicvoidchannelReadComplete(ChannelHandlerContextctx)throwsExceptionctx.flush();OverridepublicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause)ctx.close();客户端publicclassPrintClientpublicvoidconnect(intport,Stringhost)throwsExceptionEventLoopGroupgroup=new
8、NioEventLoopGroup();tryBootstrapb=newBootstrap();b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY,true).handler(newChannelInitializer()OverridepublicvoidinitChannel(SocketChannelch)throwsExceptionch.pipeline().addLast(newLineBasedFrameDecoder(1024);/3ch.pipeline().addL
9、ast(newStringDecoder();/4ch.pipeline().addLast(newPrintClientHandler(););ChannelFuturef=b.connect(host,port).sync();f.channel().closeFuture().sync();finally/优雅退出,释放NIO线程组group.shutdownGracefully();/*paramargs*throwsException*/publicstaticvoidmain(Stringargs)throwsExceptionintport=8080;newTimeClient(
10、).connect(port,);客户端的HandlerpublicclassPrintClientHandlerextendsChannelHandlerAdapterprivatestaticfinalLoggerlogger=Logger.getLogger(TimeClientHandler.class.getName();privatefinalByteBuffirstMessage;/*Createsaclient-sidehandler.*/publicTimeClientHandler()bytereq=你好服务端.getBytes();firstMessage=Unpoole
11、d.buffer(req.length);firstMessage.writeBytes(req);OverridepublicvoidchannelActive(ChannelHandlerContextctx)ctx.writeAndFlush(firstMessage);OverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg)throwsExceptionByteBufbuf=(ByteBuf)msg;bytereq=newbytebuf.readableBytes();buf.readBytes(req);Str
12、ingbody=newString(req,UTF-8);System.out.println(”服务端回应消息:+body);OverridepublicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause)/释放资源System.out.println(Unexpectedexceptionfromdownstream:+cause.getMessage();ctx.close();上诉代码逻辑与上一章代码逻辑相同,客户端接受服务端数据答应,并回复客户端信息,客户端接受到数据后打印数据。我们观察代码可以发现,要想Netty解
13、决粘包拆包问题,只需在编写服务端和客户端的pipeline上加上相应的解码器即可,上诉注释1,2,3,4处。其余代码无需做任何修改。LineBasedFrameDecoder+StringDecoder的组合就是按行切换的文本解码器,它被设计用来支持TCP的粘包和拆包。原理为:如果连续读取到最大长度后任然没有发现换行符,就会抛出异常,同时忽略掉之前督导的异常码流。DelimiteBasedFrameDecoder该解码器的可以自动完成以分割符作为码流结束标识的消息解码。(其实上一个解码器类似,如果指定分隔符为换行符,那么与上一个编码器的作用基本相同)使用也很简单:只需要修改服务端和客户端对应代
14、码中的nitChanneI代码即可publicvoidinitChannel(SocketChannelch)ByteBufdeIimiter=UnpooIed.copiedBuffer(_.getBytes();/1ch.pipeline().addLast(newDelimiterBasedFrameDecoder(1024,delimiter);/2ch.pipeline().addLast(newStringDecoder();/3ch.pipeline().addLast(newPrintHandler();注释1:首先创建分隔符缓冲对象ByteBuf,并指定以作为分隔符。注释2:将分隔符缓冲对象ByteBuf传入DelimiterBasedFrameDecoder,并指定最大长度。注释3:指定为字符串字节流FixedLengthFrameDecoder该解码器为固定长度解码器,它能够按照指定的长度对详细进行自动解码。使用同样也很简单:同样只需要修改服务端和客户端对应代码中的nitChannel代码即可publicvoidinitChannel(SocketChannelch)throwsExceptionch.pipeline().addLast(newFixedLengthFrameDecode
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 IEC 60112:2025 EN-FR Method for the determination of the proof and the comparative tracking indices of solid insulating materials
- 河南省职业学校数学试卷
- 河南禹州中招数学试卷
- 济南初三一模数学试卷
- 健康管理师课件下载
- 2025年中国刮泥机行业市场发展现状及投资规划建议报告
- 中国木材保护工业行业市场发展监测及投资潜力预测报告
- 1,4二氧六环项目可行性研究报告
- 健康知识课件下载
- 2021-2026年中国面粉加工市场调查研究及行业投资潜力预测报告
- 广东省广州市荔湾区统考2025年七下数学期末考试试题含解析
- 股权质押合同违约处理协议
- 初中德育教育家长会
- 道路危险货物运输企业安全风险辨识清单
- 老人门面分割协议书范本
- 中等职业学校医学检验技术专业教学标准(试行)
- 2025春季学期国开电大专科《管理英语1》一平台在线形考(综合测试)试题及答案
- 2025CSCO胆道恶性肿瘤诊疗指南解读
- 2025至2030中国物理气相沉积(PVD)设备行业行情监测与发展动向追踪报告
- 软式内镜消毒技术规范
- 人民调解文书规范制作
评论
0/150
提交评论