您的位置:首页 > 理论基础 > 计算机网络

Netty解决TCP粘包/拆包问题 - 按行分隔字符串解码器

2016-11-06 21:08 447 查看
服务端

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的粘包和拆包问题。

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: