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

原创 2017年09月01日 23:28:36

概述


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> {
    @Override
    protected 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;
    @Override
    public 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> {
    @Override
    protected 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;

    @Override
    public 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);
    }

    @Override
    public 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

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

SpringMVC工作原理

SpringMVC框架介绍     1) Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。 Spring 框架提供了构建 Web 应...

高德Android定位

android6.0系统需要添加运行时权限 checkPermission()方法public class MainActivity extends AppCompatActivity { ...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)