概述


TCP底层会发生粘包和拆包,这个是TCP的一个特性。为了减少网络数据传输的次数,TCP总是希望让网络数据到达一定量级的时候才将数据发送出去,而不是缓存区一有数据就马上发送数据。

TCP底层会根据缓冲区是否被填满了,来决定是否发送数据。但是从业务层面上看,这个是不合理的。因为一份业务数据可能很小,还不足以填满缓冲区,这样底层TCP就不会立刻把这份业务数据发送出去,而是等到好几份业务数据的大小填满缓冲区后才发送。这样子无论是服务端还是客户端,接收数据的时候可能会处理出错。

如果是以回车换行结尾的消息,那么组合使用

LineBasedFrameDecoder
StringDecoder

来处理半包问题。


TCP粘包拆包重现

李林锋的《netty权威指南》详细说明了TCP的粘包和拆包问题,下面就用netty权威指南》的例子作为demo。


服务端代码

package tcp.server;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;public class SocketServer {public static void main(String[] args) throws InterruptedException {EventLoopGroup parentGroup = new NioEventLoopGroup();EventLoopGroup childGroup = new NioEventLoopGroup();try {ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(parentGroup, childGroup).channel(NioServerSocketChannel.class).childHandler(new SocketServerInitializer());ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();channelFuture.channel().closeFuture().sync();}finally {parentGroup.shutdownGracefully();childGroup.shutdownGracefully();}}
}package tcp.server;import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;public class SocketServerInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new SocketServerHandler());}
}package tcp.server;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;import java.util.Date;public class SocketServerHandler extends ChannelInboundHandlerAdapter {private int counter;@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buf = (ByteBuf)msg;byte[] req = new byte[buf.readableBytes()];//将buf中的数据读取到req中buf.readBytes(req);//打印客户端发送的数据String body = new String(req, "UTF-8").substring(0, req.length - 1);System.out.println("server receive order:"+body+";the counter is:"+ ++counter);String currentTime = "";if ("QUERY TIME ORDER".equalsIgnoreCase(body)) {currentTime = new Date(System.currentTimeMillis()).toString();}else {currentTime = "BAD ORDER";}String separator = "\n";currentTime = currentTime + separator;ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());ctx.writeAndFlush(resp);}
}

客户端代码

package tcp.client;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;public class SocketClient {public static void main(String[] args) throws InterruptedException {EventLoopGroup eventLoopGroup = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new SocketClientInitializer());ChannelFuture channelFuture = bootstrap.connect("localhost", 8899).sync();channelFuture.channel().closeFuture().sync();}finally {eventLoopGroup.shutdownGracefully();}}
}package tcp.client;import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;public class SocketClientInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new SocketClientHandler());}
}package tcp.client;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;public class SocketClientHandler extends ChannelInboundHandlerAdapter {private int counter;private byte[] req;@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buf = (ByteBuf)msg;byte[] req = new byte[buf.readableBytes()];buf.readBytes(req);String body = new String(req, "UTF-8");System.out.println("Now is : " + body + " ; the counter is :"+ ++counter);}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ByteBuf message = null;for (int i = 0; i < 100; i++) {message = Unpooled.buffer(req.length);message.writeBytes(req);ctx.writeAndFlush(message);}}public SocketClientHandler() {req = ("QUERY TIME ORDER" + "\n").getBytes();}
}

当客户端与服务端建立完连接后,客户端中的SocketClientHandler类中的

channelActive

方法会被调用,往服务端发送100次请求,每个请求的内容都是

“QUERY TIME ORDER” + “\n”

当服务端接收到这些请求时,SocketServerHandler类中的

channelRead

方法会被调用,接到客户端发送的消息,如果每次收到的消息都是

QUERY TIME ORDER

那么服务端会往客户端输出当前时间。

当客户端接收到服务端的请求后,客户端类SocketClientHandler的

channelRead

方法会被调用,输出服务端返回的数据。

理论上,我们是希望客户端发送100次请求,服务端响应后,也发送100次响应。但实际上,客户端只发送了两次请求,同时服务端响应客户端的时候,只是发送了一次请求。

服务端真实打印的信息如下

server receive order:QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUE;the counter is:1
server receive order:Y TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER
QUERY TIME ORDER;the counter is:2

注意分析上面的输出,从

server receive order:QUERY TIME ORDER

到第一个

the counter is:1

中间有非常多的

QUERY TIME ORDER

说明客户端虽然发送了100次请求,但其实是累积了很多数据后,才真正的发送了一次数据。结果100次调用,最终只给服务端发送了两次请求。

既然服务端只是接收了2次请求,那么应该也给客户端发送两次请求,但是事实上只发送了一次,客户端的输出结果如下

Now is : BAD ORDER
BAD ORDER; the counter is :1

有两个

BAD ORDER

说明服务端只给客户端发送了一次请求。

到此我们得出结论,在这个例子中

客户端和服务端都发送了粘包


netty自带的解码器解决粘包和拆包问题


可以使用自带的

LineBasedFrameDecoder和StringDecoder

解码器来解决这个问题,我们稍微调整一下代码。

在SocketServerInitializer类中加入

pipeline.addLast(new LineBasedFrameDecoder(1024));
pipeline.addLast(new StringDecoder());

在SocketClientInitializer类中也加入

pipeline.addLast(new LineBasedFrameDecoder(1024));
pipeline.addLast(new StringDecoder());

将SocketServerHandler类channelRead方法中的

ByteBuf buf = (ByteBuf)msg;
byte[] req = new byte[buf.readableBytes()];
//将buf中的数据读取到req中buf.readBytes(req);//打印客户端发送的数据String body = new String(req, "UTF-8").substring(0, req.length - 1);

用下面一行代码替换即可

String body = (String)msg;

同样也将SocketClientHandler类中channelRead方法中的

 ByteBuf buf = (ByteBuf)msg;byte[] req = new byte[buf.readableBytes()];buf.readBytes(req);String body = new String(req, "UTF-8");

换成

String body = (String)msg;

接下来运行服务端和客户端,发现输出结果已经正常了。
服务端输出

server receive order:QUERY TIME ORDER;the counter is:1
server receive order:QUERY TIME ORDER;the counter is:2
server receive order:QUERY TIME ORDER;the counter is:3
server receive order:QUERY TIME ORDER;the counter is:4
server receive order:QUERY TIME ORDER;the counter is:5
server receive order:QUERY TIME ORDER;the counter is:6
server receive order:QUERY TIME ORDER;the counter is:7
server receive order:QUERY TIME ORDER;the counter is:8
server receive order:QUERY TIME ORDER;the counter is:9
server receive order:QUERY TIME ORDER;the counter is:10
server receive order:QUERY TIME ORDER;the counter is:11
server receive order:QUERY TIME ORDER;the counter is:12
server receive order:QUERY TIME ORDER;the counter is:13
server receive order:QUERY TIME ORDER;the counter is:14
server receive order:QUERY TIME ORDER;the counter is:15
server receive order:QUERY TIME ORDER;the counter is:16
server receive order:QUERY TIME ORDER;the counter is:17
server receive order:QUERY TIME ORDER;the counter is:18
server receive order:QUERY TIME ORDER;the counter is:19
server receive order:QUERY TIME ORDER;the counter is:20
server receive order:QUERY TIME ORDER;the counter is:21
server receive order:QUERY TIME ORDER;the counter is:22
server receive order:QUERY TIME ORDER;the counter is:23
server receive order:QUERY TIME ORDER;the counter is:24
server receive order:QUERY TIME ORDER;the counter is:25
server receive order:QUERY TIME ORDER;the counter is:26
server receive order:QUERY TIME ORDER;the counter is:27
server receive order:QUERY TIME ORDER;the counter is:28
server receive order:QUERY TIME ORDER;the counter is:29
server receive order:QUERY TIME ORDER;the counter is:30
server receive order:QUERY TIME ORDER;the counter is:31
server receive order:QUERY TIME ORDER;the counter is:32
server receive order:QUERY TIME ORDER;the counter is:33
server receive order:QUERY TIME ORDER;the counter is:34
server receive order:QUERY TIME ORDER;the counter is:35
server receive order:QUERY TIME ORDER;the counter is:36
server receive order:QUERY TIME ORDER;the counter is:37
server receive order:QUERY TIME ORDER;the counter is:38
server receive order:QUERY TIME ORDER;the counter is:39
server receive order:QUERY TIME ORDER;the counter is:40
server receive order:QUERY TIME ORDER;the counter is:41
server receive order:QUERY TIME ORDER;the counter is:42
server receive order:QUERY TIME ORDER;the counter is:43
server receive order:QUERY TIME ORDER;the counter is:44
server receive order:QUERY TIME ORDER;the counter is:45
server receive order:QUERY TIME ORDER;the counter is:46
server receive order:QUERY TIME ORDER;the counter is:47
server receive order:QUERY TIME ORDER;the counter is:48
server receive order:QUERY TIME ORDER;the counter is:49
server receive order:QUERY TIME ORDER;the counter is:50
server receive order:QUERY TIME ORDER;the counter is:51
server receive order:QUERY TIME ORDER;the counter is:52
server receive order:QUERY TIME ORDER;the counter is:53
server receive order:QUERY TIME ORDER;the counter is:54
server receive order:QUERY TIME ORDER;the counter is:55
server receive order:QUERY TIME ORDER;the counter is:56
server receive order:QUERY TIME ORDER;the counter is:57
server receive order:QUERY TIME ORDER;the counter is:58
server receive order:QUERY TIME ORDER;the counter is:59
server receive order:QUERY TIME ORDER;the counter is:60
server receive order:QUERY TIME ORDER;the counter is:61
server receive order:QUERY TIME ORDER;the counter is:62
server receive order:QUERY TIME ORDER;the counter is:63
server receive order:QUERY TIME ORDER;the counter is:64
server receive order:QUERY TIME ORDER;the counter is:65
server receive order:QUERY TIME ORDER;the counter is:66
server receive order:QUERY TIME ORDER;the counter is:67
server receive order:QUERY TIME ORDER;the counter is:68
server receive order:QUERY TIME ORDER;the counter is:69
server receive order:QUERY TIME ORDER;the counter is:70
server receive order:QUERY TIME ORDER;the counter is:71
server receive order:QUERY TIME ORDER;the counter is:72
server receive order:QUERY TIME ORDER;the counter is:73
server receive order:QUERY TIME ORDER;the counter is:74
server receive order:QUERY TIME ORDER;the counter is:75
server receive order:QUERY TIME ORDER;the counter is:76
server receive order:QUERY TIME ORDER;the counter is:77
server receive order:QUERY TIME ORDER;the counter is:78
server receive order:QUERY TIME ORDER;the counter is:79
server receive order:QUERY TIME ORDER;the counter is:80
server receive order:QUERY TIME ORDER;the counter is:81
server receive order:QUERY TIME ORDER;the counter is:82
server receive order:QUERY TIME ORDER;the counter is:83
server receive order:QUERY TIME ORDER;the counter is:84
server receive order:QUERY TIME ORDER;the counter is:85
server receive order:QUERY TIME ORDER;the counter is:86
server receive order:QUERY TIME ORDER;the counter is:87
server receive order:QUERY TIME ORDER;the counter is:88
server receive order:QUERY TIME ORDER;the counter is:89
server receive order:QUERY TIME ORDER;the counter is:90
server receive order:QUERY TIME ORDER;the counter is:91
server receive order:QUERY TIME ORDER;the counter is:92
server receive order:QUERY TIME ORDER;the counter is:93
server receive order:QUERY TIME ORDER;the counter is:94
server receive order:QUERY TIME ORDER;the counter is:95
server receive order:QUERY TIME ORDER;the counter is:96
server receive order:QUERY TIME ORDER;the counter is:97
server receive order:QUERY TIME ORDER;the counter is:98
server receive order:QUERY TIME ORDER;the counter is:99
server receive order:QUERY TIME ORDER;the counter is:100

客户端输出

Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :1
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :2
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :3
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :4
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :5
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :6
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :7
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :8
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :9
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :10
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :11
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :12
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :13
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :14
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :15
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :16
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :17
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :18
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :19
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :20
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :21
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :22
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :23
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :24
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :25
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :26
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :27
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :28
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :29
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :30
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :31
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :32
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :33
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :34
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :35
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :36
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :37
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :38
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :39
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :40
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :41
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :42
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :43
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :44
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :45
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :46
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :47
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :48
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :49
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :50
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :51
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :52
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :53
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :54
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :55
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :56
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :57
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :58
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :59
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :60
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :61
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :62
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :63
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :64
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :65
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :66
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :67
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :68
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :69
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :70
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :71
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :72
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :73
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :74
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :75
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :76
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :77
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :78
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :79
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :80
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :81
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :82
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :83
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :84
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :85
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :86
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :87
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :88
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :89
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :90
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :91
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :92
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :93
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :94
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :95
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :96
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :97
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :98
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :99
Now is : Fri Sep 01 19:48:07 CST 2017 ; the counter is :100

如此看来直接使用netty自带的解码器可以完美解决粘包问题,当然拆包问题也是使用这两个解码器就可以搞定了。非常的方便。


csdn code 路径


这个项目的源代码放置在csdn code上,欢迎访问。
netty_study

netty权威指南笔记-以回车换行结尾的消息如何处理半包问题相关推荐

  1. 《Netty权威指南》笔记 —— 第二十、二十一、二十二, 二十三章

    <Netty权威指南>笔记--Netty高级特性 第20章 Netty架构剖析 Reactor通信调度层 职责链 ChannelPipeline 业务逻辑编排层 关键架构质量属性 高性能 ...

  2. netty权威指南学习笔记五——分隔符和定长解码器的应用

    TCP以流的方式进行数据传输,上层应用协议为了对消息进行区分,通常采用以下4中方式: 消息长度固定,累计读取到长度综合为定长LEN的报文后,就认为读取到了一个完整的消息,将计数器置位,重新开始读取下一 ...

  3. 《Netty权威指南 第2版》学习笔记(1)---服务端与客户端开发入门

    前言 Netty权威指南中以时间服务器为入门案例,演示了如何通过Netty完成了服务端与客户端之间的交互过程. 在开始使用Netty开发之前,先回顾一下使用NIO进行服务端开发的步骤. 创建Serve ...

  4. netty权威指南 学习笔记http

    序 李林峰的<netty权威指南>,从Java的NIO开始介绍,后面介绍TCP粘包拆包.中级篇介绍编解码技术. 第10章介绍了HTTP及netty HTTP+XML的技术. 因为xml实际 ...

  5. Netty权威指南(四)TCP粘包/拆包问题

    TCP粘包/拆包问题解决之道 上一章 一.介绍 1.1 TCP粘包/拆包问题说明 1.2 TCP粘包/拆包发生的原因 1.3 粘包问题的解决策略 二.未考虑TCP粘包导致的功能异常案例 2.1 Tim ...

  6. 《Netty权威指南》

    <Netty权威指南> 基本信息 作者: 李林锋 出版社:电子工业出版社 ISBN:9787121233432 上架时间:2014-5-29 出版日期:2014 年6月 开本:16开 页码 ...

  7. HTML5与CSS3权威指南笔记案例1

    第1章 <!DOCTYPE html> <meta charset = "UTF-8"> <title> Search </title&g ...

  8. [201504][Netty 权威指南][第2版][李林锋][著]

    [201504][Netty 权威指南][第2版][李林锋][著] https://github.com/wuyinxian124/nettybook2 基础篇 走进 Java NIO 第 1 章 J ...

  9. IT人物之《Netty权威指南》中文作者 专访华为李林锋:我与Netty那些不得不说的事

    摘要:Netty是业界最流行的NIO框架之一,它的健壮性.功能.性能.可定制性和可扩展性在同类框架中都是首屈一指的.近日,CSDN采访了Netty领域的权威人士李林锋,请他分享Netty开发的经验之道 ...

最新文章

  1. mybatis学习3之分页的实现
  2. Linux调优方案,sysctl.conf的设置
  3. Javascript实现导航锚点滚动效果实例
  4. 窥探SnowflakeIdWorker之并发生成唯一ID
  5. bootstrat 设置 select option 选项的值
  6. 领域应用 | 到底什么时候使用图数据库?
  7. 楼房顶顶面起渣是何原因?怎么修补?
  8. C++ typename的使用方式
  9. ieee5节点系统图_存储系统的的关键技术之自精简技术
  10. python之路-操作系统
  11. java基础--ObjectInputStream和ObjectInputStream类
  12. ssm企业人事管理系统人事管理系统(企业人事管理系统)企业人事人力资源管理系统
  13. iTextSharp生成pdf文档案例
  14. 微信扫一扫二维码直接打开外部浏览器下载app怎么解决
  15. Learn Git Branching 小游戏总结
  16. cql oracle,Cassandra CQL中的Where和Order By子句
  17. 算法题6 b站扭蛋机
  18. 在船舶共轨实验平台上使用Mbed LPC1768
  19. 中国电信北京研究院 孙琼:中国电信的SDN应用与实践初探
  20. (MATLAB)散点椭圆拟合与绘制代码

热门文章

  1. mysql提示2002错误的解决方法
  2. 大一软件工程要学什么
  3. Zhishi.me - Weaving Chinese Linking Open Data
  4. ps照片人像油画复古效果怎么做
  5. 从战略到执行:业务领先模型 BLM 战略篇「战略意图」
  6. 不是所有的大作业都叫微信抢票大作业
  7. 关于 Photoshop 图层
  8. 分水岭算法 c语言实现,分水岭算法的应用
  9. 百度java面试应届,秋招 百度二轮面试---血淋淋的经历写实
  10. 三个灭点来衡量一个立方体