一:TCP粘包拆包简介
TCP是个"流"协议,底层并不了解上次业务数据的具体含义,它是根据TCP缓冲区的实际情况对数据包进行划分,所以在数据传输过程中一个完整的数据包可能会被TCP拆分成多个包进行发送,也有可能把多个小的数据包封装成一个大的数据包发送,这就是TCP的粘包拆包问题。
二:粘包拆包的解决思路
由于底层的TCP无法理解上层的业务数据,所以解决思路只能通过上层的应用协议栈设计来解决,目前主流协议的解决方案有:
(1)消息定长,如长度200个字节,不够的补空格;
(2)在数据包结尾添加回车换行符进行分割,如FTP协议;
(3)将消息分为消息头和消息体,消息头中包含消息的总长度。
三:Netty关于粘包拆包的解决方案
对于数据量较小时并不会出现粘包问题,但当数据报文较大时,或者压力一旦上来,就会存在粘包拆包问题。下面将模拟粘包拆包案例。
1、TimeServer
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class TimeServer {
public void bind(int port) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024).childHandler(new ChildChannelHandler());
ChannelFuture f = bootstrap.bind(port).sync();
f.channel().closeFuture().sync();
} catch (Exception e) {
// TODO: handle exception
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
new TimeServer().bind(8080);
}
}
class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel arg0) throws Exception {
// TODO Auto-generated method stub
arg0.pipeline().addLast(new TimeServerHandler());
}
}
2、TimeServerHandler
import java.util.Date;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
public class TimeServerHandler extends ChannelHandlerAdapter{
private int counter;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8").substring(0, req.length - System.getProperty("line.separator").length());
System.out.println("the time server receive order :" + body+"; the counter is "+ ++counter);
String currentyTime = "QUERY TIME ORDER".equalsIgnoreCase(body)
? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";
currentyTime = currentyTime + System.getProperty("line.separator");
ByteBuf copiedBuffer = Unpooled.copiedBuffer(currentyTime.getBytes());
ctx.write(copiedBuffer);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
ctx.close();
}
}
3、TimeClient
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class TimeClient {
public void connect(String host, int port) {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel s) throws Exception {
s.pipeline().addLast(new TimeClienHandler());
};
});
ChannelFuture f = bootstrap.connect(host, port).sync();
f.channel().closeFuture().sync();
} catch (Exception e) {
// TODO: handle exception
} finally {
group.shutdownGracefully();
}
}
public static void main(String[] args) {
new TimeClient().connect("127.0.0.1", 8080);
}
}
4、TimeClienHandler
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
public class TimeClienHandler extends ChannelHandlerAdapter {
private int counter;
private final byte[] req;
// private final ByteBuf buf;
public TimeClienHandler() {
req = ("QUERY TIME ORDER" + System.getProperty("line.separator")).getBytes();
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
ByteBuf message = null;
for (int i = 0; i < 100; i++) {
message = Unpooled.buffer(req.length);
message.writeBytes(req);
ctx.writeAndFlush(message);
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
// String body = (String) msg;
System.out.println("now is :" + body + "; the counter is :" + ++counter);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
ctx.close();
}
}
运行结果如下:
服务器端:
the time 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 ORD; the counter is 1
the time 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; the counter is 2
客户端:
now is :BAD ORDER
BAD ORDER
; the counter is :1
测试说明:
如果不出现粘包问题,服务器端预期收到的应该是:
the time server receive order :QUERY TIME ORDER ; the counter is :1
这样的100条消息,客户端预期收到的应该是:
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :1
这样的100条消息,但实际测试确出现了上述的测试结果,说明在传输过程中出现了粘包问题。下面利用Netty提供的编码器解决TCP粘包拆包问题(LineBasedFrameDecoder&&StringDecoder)。
1、TimeServer
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
/**
* 编码器LineBasedFrameDecoder && StringDecoder
*/
public class TimeServer {
public void bind(int port) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024).childHandler(new ChildChannelHandler());
ChannelFuture f = bootstrap.bind(port).sync();
f.channel().closeFuture().sync();
} catch (Exception e) {
// TODO: handle exception
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
new TimeServer().bind(8080);
}
}
class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel arg0) throws Exception {
// TODO Auto-generated method stub
arg0.pipeline().addLast(new LineBasedFrameDecoder(1024));
arg0.pipeline().addLast(new StringDecoder());
arg0.pipeline().addLast(new TimeHandler());
}
}
2、TimeServerHandler
import java.util.Date;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
public class TimeServerHandler extends ChannelHandlerAdapter {
private int counter;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
String s = (String) msg;
System.out.println("the time server receive order :" + s + " ; the counter is :" + ++counter);
String currentyTime = "QUERY TIME ORDER".equalsIgnoreCase(s) ? new Date(System.currentTimeMillis()).toString()
: "BAD ORDER";
currentyTime = currentyTime + System.getProperty("line.separator");
ByteBuf copiedBuffer = Unpooled.copiedBuffer(currentyTime.getBytes());
ctx.write(copiedBuffer);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
ctx.close();
}
}
3、TimeClient
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
public class TimeClient {
public void connect(String host, int port) {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel s) throws Exception {
s.pipeline().addLast(new LineBasedFrameDecoder(1024));
s.pipeline().addLast(new StringDecoder());
s.pipeline().addLast(new TimeClienHandler());
};
});
ChannelFuture f = bootstrap.connect(host, port).sync();
f.channel().closeFuture().sync();
} catch (Exception e) {
// TODO: handle exception
} finally {
group.shutdownGracefully();
}
}
public static void main(String[] args) {
new TimeClient().connect("127.0.0.1", 8080);
}
}
4、TimeClienHandler
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
public class TimeClienHandler extends ChannelHandlerAdapter {
private int counter;
private final byte[] req;
public TimeClienHandler() {
req = ("QUERY TIME ORDER" + System.getProperty("line.separator")).getBytes();
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
ByteBuf message = null;
for (int i = 0; i < 100; i++) {
message = Unpooled.buffer(req.length);
message.writeBytes(req);
ctx.writeAndFlush(message);
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
String body = (String) msg;
System.out.println("now is :" + body + "; the counter is :" + ++counter);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
ctx.close();
}
}
运行结果如下:
服务器端:
the time server receive order :QUERY TIME ORDER ; the counter is :1
the time server receive order :QUERY TIME ORDER ; the counter is :2
the time server receive order :QUERY TIME ORDER ; the counter is :3
the time server receive order :QUERY TIME ORDER ; the counter is :4
the time server receive order :QUERY TIME ORDER ; the counter is :5
the time server receive order :QUERY TIME ORDER ; the counter is :6
the time server receive order :QUERY TIME ORDER ; the counter is :7
the time server receive order :QUERY TIME ORDER ; the counter is :8
the time server receive order :QUERY TIME ORDER ; the counter is :9
the time server receive order :QUERY TIME ORDER ; the counter is :10
the time server receive order :QUERY TIME ORDER ; the counter is :11
the time server receive order :QUERY TIME ORDER ; the counter is :12
the time server receive order :QUERY TIME ORDER ; the counter is :13
the time server receive order :QUERY TIME ORDER ; the counter is :14
the time server receive order :QUERY TIME ORDER ; the counter is :15
the time server receive order :QUERY TIME ORDER ; the counter is :16
the time server receive order :QUERY TIME ORDER ; the counter is :17
the time server receive order :QUERY TIME ORDER ; the counter is :18
the time server receive order :QUERY TIME ORDER ; the counter is :19
the time server receive order :QUERY TIME ORDER ; the counter is :20
the time server receive order :QUERY TIME ORDER ; the counter is :21
the time server receive order :QUERY TIME ORDER ; the counter is :22
the time server receive order :QUERY TIME ORDER ; the counter is :23
the time server receive order :QUERY TIME ORDER ; the counter is :24
the time server receive order :QUERY TIME ORDER ; the counter is :25
the time server receive order :QUERY TIME ORDER ; the counter is :26
the time server receive order :QUERY TIME ORDER ; the counter is :27
the time server receive order :QUERY TIME ORDER ; the counter is :28
the time server receive order :QUERY TIME ORDER ; the counter is :29
the time server receive order :QUERY TIME ORDER ; the counter is :30
the time server receive order :QUERY TIME ORDER ; the counter is :31
the time server receive order :QUERY TIME ORDER ; the counter is :32
the time server receive order :QUERY TIME ORDER ; the counter is :33
the time server receive order :QUERY TIME ORDER ; the counter is :34
the time server receive order :QUERY TIME ORDER ; the counter is :35
the time server receive order :QUERY TIME ORDER ; the counter is :36
the time server receive order :QUERY TIME ORDER ; the counter is :37
the time server receive order :QUERY TIME ORDER ; the counter is :38
the time server receive order :QUERY TIME ORDER ; the counter is :39
the time server receive order :QUERY TIME ORDER ; the counter is :40
the time server receive order :QUERY TIME ORDER ; the counter is :41
the time server receive order :QUERY TIME ORDER ; the counter is :42
the time server receive order :QUERY TIME ORDER ; the counter is :43
the time server receive order :QUERY TIME ORDER ; the counter is :44
the time server receive order :QUERY TIME ORDER ; the counter is :45
the time server receive order :QUERY TIME ORDER ; the counter is :46
the time server receive order :QUERY TIME ORDER ; the counter is :47
the time server receive order :QUERY TIME ORDER ; the counter is :48
the time server receive order :QUERY TIME ORDER ; the counter is :49
the time server receive order :QUERY TIME ORDER ; the counter is :50
the time server receive order :QUERY TIME ORDER ; the counter is :51
the time server receive order :QUERY TIME ORDER ; the counter is :52
the time server receive order :QUERY TIME ORDER ; the counter is :53
the time server receive order :QUERY TIME ORDER ; the counter is :54
the time server receive order :QUERY TIME ORDER ; the counter is :55
the time server receive order :QUERY TIME ORDER ; the counter is :56
the time server receive order :QUERY TIME ORDER ; the counter is :57
the time server receive order :QUERY TIME ORDER ; the counter is :58
the time server receive order :QUERY TIME ORDER ; the counter is :59
the time server receive order :QUERY TIME ORDER ; the counter is :60
the time server receive order :QUERY TIME ORDER ; the counter is :61
the time server receive order :QUERY TIME ORDER ; the counter is :62
the time server receive order :QUERY TIME ORDER ; the counter is :63
the time server receive order :QUERY TIME ORDER ; the counter is :64
the time server receive order :QUERY TIME ORDER ; the counter is :65
the time server receive order :QUERY TIME ORDER ; the counter is :66
the time server receive order :QUERY TIME ORDER ; the counter is :67
the time server receive order :QUERY TIME ORDER ; the counter is :68
the time server receive order :QUERY TIME ORDER ; the counter is :69
the time server receive order :QUERY TIME ORDER ; the counter is :70
the time server receive order :QUERY TIME ORDER ; the counter is :71
the time server receive order :QUERY TIME ORDER ; the counter is :72
the time server receive order :QUERY TIME ORDER ; the counter is :73
the time server receive order :QUERY TIME ORDER ; the counter is :74
the time server receive order :QUERY TIME ORDER ; the counter is :75
the time server receive order :QUERY TIME ORDER ; the counter is :76
the time server receive order :QUERY TIME ORDER ; the counter is :77
the time server receive order :QUERY TIME ORDER ; the counter is :78
the time server receive order :QUERY TIME ORDER ; the counter is :79
the time server receive order :QUERY TIME ORDER ; the counter is :80
the time server receive order :QUERY TIME ORDER ; the counter is :81
the time server receive order :QUERY TIME ORDER ; the counter is :82
the time server receive order :QUERY TIME ORDER ; the counter is :83
the time server receive order :QUERY TIME ORDER ; the counter is :84
the time server receive order :QUERY TIME ORDER ; the counter is :85
the time server receive order :QUERY TIME ORDER ; the counter is :86
the time server receive order :QUERY TIME ORDER ; the counter is :87
the time server receive order :QUERY TIME ORDER ; the counter is :88
the time server receive order :QUERY TIME ORDER ; the counter is :89
the time server receive order :QUERY TIME ORDER ; the counter is :90
the time server receive order :QUERY TIME ORDER ; the counter is :91
the time server receive order :QUERY TIME ORDER ; the counter is :92
the time server receive order :QUERY TIME ORDER ; the counter is :93
the time server receive order :QUERY TIME ORDER ; the counter is :94
the time server receive order :QUERY TIME ORDER ; the counter is :95
the time server receive order :QUERY TIME ORDER ; the counter is :96
the time server receive order :QUERY TIME ORDER ; the counter is :97
the time server receive order :QUERY TIME ORDER ; the counter is :98
the time server receive order :QUERY TIME ORDER ; the counter is :99
the time server receive order :QUERY TIME ORDER ; the counter is :100
客户端:
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :1
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :2
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :3
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :4
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :5
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :6
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :7
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :8
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :9
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :10
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :11
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :12
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :13
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :14
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :15
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :16
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :17
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :18
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :19
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :20
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :21
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :22
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :23
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :24
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :25
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :26
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :27
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :28
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :29
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :30
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :31
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :32
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :33
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :34
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :35
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :36
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :37
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :38
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :39
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :40
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :41
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :42
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :43
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :44
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :45
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :46
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :47
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :48
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :49
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :50
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :51
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :52
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :53
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :54
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :55
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :56
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :57
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :58
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :59
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :60
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :61
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :62
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :63
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :64
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :65
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :66
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :67
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :68
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :69
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :70
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :71
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :72
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :73
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :74
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :75
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :76
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :77
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :78
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :79
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :80
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :81
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :82
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :83
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :84
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :85
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :86
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :87
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :88
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :89
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :90
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :91
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :92
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :93
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :94
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :95
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :96
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :97
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :98
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :99
now is :Mon Sep 21 10:33:17 CST 2015; the counter is :100
测试说明:
测试结果正确的收到了消息,说明LineBasedFrameDecoder和StringDecoder成功解决了TCP的粘包问题。
除了上述的解码器,Netty还提供了多种支持TCP粘包拆包的解码器,用来满足不同的用户需求,在接下来的文章中将继续讲解这些解码器。