Netty解决TCP粘包/拆包问题 - 按行分隔字符串解码器
2016-11-06 21:08
447 查看
服务端
TimerClientHandler
这里主要使用 LineBasedFrameDecoder 和 StringDecoder 来实现解决粘包问题
原理如下:
LineBasedFrameDecoder 依次遍历 ByteBuf 中的可读字节,判断是否有 \n 或 \r\n,如果有,就作为结束位置。从可读索引到结束位置区间的字节组成一行。它是以换行符为结束标志的解码器。支持携带结束符或者不懈怠结束符两种解码方式。同时支持配置单行的最大长度。如果读取到了最大长度仍旧没有发现换行符,就会抛出异常,同时忽略掉之前读到的数据。
StringDecoder 的作用就是讲接收到的对象转化成字符串,然后继续调用handler。这样就不需要再handler中手动将对象转化成字符串了,直接强制转化就行。
LineBasedFrameDecoder+StringDecoder组合就是按行切割的文本解码器,用来解决TCP的粘包和拆包问题。
1 package org.zln.netty.five.timer; 2 3 import io.netty.buffer.ByteBuf; 4 import io.netty.buffer.Unpooled; 5 import io.netty.channel.ChannelHandlerAdapter; 6 import io.netty.channel.ChannelHandlerContext; 7 import org.slf4j.Logger; 8 import org.slf4j.LoggerFactory; 9 10 import java.io.UnsupportedEncodingException; 11 12 /** 13 * Created by sherry on 16/11/5. 14 */ 15 public class TimerClientHandler extends ChannelHandlerAdapter { 16 17 /** 18 * 日志 19 */ 20 private Logger logger = LoggerFactory.getLogger(TimerClientHandler.class); 21 22 private static int count = 0; 23 24 @Override 25 public void channelActive(ChannelHandlerContext ctx) throws Exception { 26 logger.debug("客户端连接上了服务端"); 27 28 //发送请求 29 ByteBuf reqBuf = null; 30 for (int i = 0; i < 100; i++) { 31 reqBuf = getReq("GET TIME"+System.lineSeparator()); 32 ctx.writeAndFlush(reqBuf); 33 } 34 35 36 } 37 38 /** 39 * 将字符串包装成ByteBuf 40 * @param s 41 * @return 42 */ 43 private ByteBuf getReq(String s) throws UnsupportedEncodingException { 44 byte[] data = s.getBytes("UTF-8"); 45 ByteBuf reqBuf = Unpooled.buffer(data.length); 46 reqBuf.writeBytes(data); 47 return reqBuf; 48 } 49 50 @Override 51 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 52 String body = (String) msg; 53 logger.debug("这是收到的第 "+(++count)+" 笔响应 -- "+body); 54 } 55 56 @Override 57 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 58 ctx.close(); 59 } 60 }
TimerClientHandler
这里主要使用 LineBasedFrameDecoder 和 StringDecoder 来实现解决粘包问题
原理如下:
LineBasedFrameDecoder 依次遍历 ByteBuf 中的可读字节,判断是否有 \n 或 \r\n,如果有,就作为结束位置。从可读索引到结束位置区间的字节组成一行。它是以换行符为结束标志的解码器。支持携带结束符或者不懈怠结束符两种解码方式。同时支持配置单行的最大长度。如果读取到了最大长度仍旧没有发现换行符,就会抛出异常,同时忽略掉之前读到的数据。
StringDecoder 的作用就是讲接收到的对象转化成字符串,然后继续调用handler。这样就不需要再handler中手动将对象转化成字符串了,直接强制转化就行。
LineBasedFrameDecoder+StringDecoder组合就是按行切割的文本解码器,用来解决TCP的粘包和拆包问题。
相关文章推荐
- 逗号分隔字符串转换为一张表--解决查询in(逗号分隔字符串)出错问题
- OLEDB方式操作规则EXCEL的字符串的完整写法(解决标题行和列数据类型不一致的问题)
- 使用hibernate心得——字符串超长的解决办法(setCharacterStream出现顺序问题)
- 用enum类型数据解决switch case选择字符串的问题
- 长字符串显示引起的问题通用性解决方法
- 用CSS解决中英文混合字符串的截取省略问题的解决办法
- 安全字符串 SecureString 的设计与实现 [1] 现有问题与解决方法
- symbian中文字符串显示问题的解决
- 解决replaceAll替换字符串中包括特殊符号时出现的问题
- 大数问题:用字符串解决大数相加和相乘
- 关于子函数返回字符串的问题解决办法
- symbian中文字符串显示问题的解决(转载)
- 关于网友说的gridview不能格式化字符串的问题的解决办法
- 也用switch case 解决字符串选择的问题
- java字符串星号、问号匹配问题解决方法
- java字符串星号、问号匹配问题解决方法
- 对于字符串向smalldatetime转换失败问题的解决
- smarty模板截取字符串乱码问题完美解决```````
- C#中解决在STRING.SPLIT()中不能用字符串分割另一字符串的问题