精华内容
下载资源
问答
  • 如果是以回车换行结尾消息,那么组合使用 LineBasedFrameDecoder StringDecoder 来处理半包问题。 TCP粘包拆包重现 李林锋的《netty权威指南》详细说明了TCP的粘包和拆包问题,下面就用...

    概述


    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

    展开全文
  • 请参见此消息结尾。 ************** 异常文本 ************** System.NullReferenceException: 未将对象引用设置到对象的实例。 在 ZuHaoFrm.FrmMain.Form1_Load(Object sender, EventArgs e) 在 Sy

    可能是对象未实例化

    有关调用实时(JIT)调试而不是此对话框的详细信息,
    请参见此消息的结尾。
    
    ************** 异常文本 **************
    System.NullReferenceException: 未将对象引用设置到对象的实例。
       在 ZuHaoFrm.FrmMain.Form1_Load(Object sender, EventArgs e)
       在 System.Windows.Forms.Form.OnLoad(EventArgs e)
       在 System.Windows.Forms.Form.OnCreateControl()
       在 System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
       在 System.Windows.Forms.Control.CreateControl()
       在 System.Windows.Forms.Control.WmShowWindow(Message& m)
       在 System.Windows.Forms.Control.WndProc(Message& m)
       在 System.Windows.Forms.ScrollableControl.WndProc(Message& m)
       在 System.Windows.Forms.Form.WmShowWindow(Message& m)
       在 System.Windows.Forms.Form.WndProc(Message& m)
       在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       在 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    
    
    ************** 已加载的程序集 **************
    mscorlib
        程序集版本:4.0.0.0
        Win32 版本:4.7.2114.0 built by: NET47REL1LAST
        基本代码:file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll
    ----------------------------------------
    ZuHaoFrm
        程序集版本:1.0.0.0
        Win32 版本:1.0.0.0
        基本代码:file:///C:/WorkSpace/%E7%95%85%E7%A7%9F%E7%BD%91%E5%AE%A2%E6%88%B7%E7%AB%AF/ZuHaoFrm.exe
    ----------------------------------------
    System.Windows.Forms
        程序集版本:4.0.0.0
        Win32 版本:4.7.2114.0 built by: NET47REL1LAST
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
    ----------------------------------------
    System
        程序集版本:4.0.0.0
        Win32 版本:4.7.2114.0 built by: NET47REL1LAST
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System/v4.0_4.0.0.0__b77a5c561934e089/System.dll
    ----------------------------------------
    System.Drawing
        程序集版本:4.0.0.0
        Win32 版本:4.7.2114.0 built by: NET47REL1LAST
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Drawing/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
    ----------------------------------------
    log4net
        程序集版本:1.2.15.0
        Win32 版本:1.2.15.0
        基本代码:file:///C:/WorkSpace/%E7%95%85%E7%A7%9F%E7%BD%91%E5%AE%A2%E6%88%B7%E7%AB%AF/log4net.DLL
    ----------------------------------------
    WYL.Framework
        程序集版本:1.0.0.0
        Win32 版本:1.0.0.0
        基本代码:file:///C:/WorkSpace/%E7%95%85%E7%A7%9F%E7%BD%91%E5%AE%A2%E6%88%B7%E7%AB%AF/WYL.Framework.DLL
    ----------------------------------------
    System.Configuration
        程序集版本:4.0.0.0
        Win32 版本:4.6.1099.0 built by: NETFXREL4STAGE
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Configuration/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
    ----------------------------------------
    System.Core
        程序集版本:4.0.0.0
        Win32 版本:4.7.2114.0 built by: NET47REL1LAST
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Core/v4.0_4.0.0.0__b77a5c561934e089/System.Core.dll
    ----------------------------------------
    System.Xml
        程序集版本:4.0.0.0
        Win32 版本:4.7.2114.0 built by: NET47REL1LAST
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Xml/v4.0_4.0.0.0__b77a5c561934e089/System.Xml.dll
    ----------------------------------------
    HttpCodeLib
        程序集版本:4.1.17.8
        Win32 版本:4.1.17.08
        基本代码:file:///C:/WorkSpace/%E7%95%85%E7%A7%9F%E7%BD%91%E5%AE%A2%E6%88%B7%E7%AB%AF/HttpCodeLib.DLL
    ----------------------------------------
    Newtonsoft.Json
        程序集版本:4.5.0.0
        Win32 版本:4.5.11.15520
        基本代码:file:///C:/WorkSpace/%E7%95%85%E7%A7%9F%E7%BD%91%E5%AE%A2%E6%88%B7%E7%AB%AF/Newtonsoft.Json.DLL
    ----------------------------------------
    System.ComponentModel.DataAnnotations
        程序集版本:4.0.0.0
        Win32 版本:4.7.2114.0
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.ComponentModel.DataAnnotations/v4.0_4.0.0.0__31bf3856ad364e35/System.ComponentModel.DataAnnotations.dll
    ----------------------------------------
    System.Runtime.Serialization
        程序集版本:4.0.0.0
        Win32 版本:4.7.2114.0 built by: NET47REL1LAST
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Runtime.Serialization/v4.0_4.0.0.0__b77a5c561934e089/System.Runtime.Serialization.dll
    ----------------------------------------
    System.Xml.Linq
        程序集版本:4.0.0.0
        Win32 版本:4.6.1099.0 built by: NETFXREL4STAGE
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Xml.Linq/v4.0_4.0.0.0__b77a5c561934e089/System.Xml.Linq.dll
    ----------------------------------------
    System.Data
        程序集版本:4.0.0.0
        Win32 版本:4.7.2114.0 built by: NET47REL1LAST
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_32/System.Data/v4.0_4.0.0.0__b77a5c561934e089/System.Data.dll
    ----------------------------------------
    mscorlib.resources
        程序集版本:4.0.0.0
        Win32 版本:4.6.1055.0 built by: NETFXREL2
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/mscorlib.resources/v4.0_4.0.0.0_zh-Hans_b77a5c561934e089/mscorlib.resources.dll
    ----------------------------------------
    System.Windows.Forms.resources
        程序集版本:4.0.0.0
        Win32 版本:4.6.1055.0 built by: NETFXREL2
        基本代码:file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms.resources/v4.0_4.0.0.0_zh-Hans_b77a5c561934e089/System.Windows.Forms.resources.dll
    ----------------------------------------
    
    ************** JIT 调试 **************
    要启用实时(JIT)调试,
    该应用程序或计算机的 .config 文件(machine.config)的 system.windows.forms 节中必须设置
    jitDebugging 值。
    编译应用程序时还必须启用
    调试。
    
    例如:
    
    <configuration>
        <system.windows.forms jitDebugging="true" />
    </configuration>
    
    启用 JIT 调试后,任何未经处理的异常
    都将被发送到在此计算机上注册的 JIT 调试器,
    而不是由此对话框处理。
    
    
    
    
    展开全文
  • ros工具可以根据消息描述为消息类型生成不同目标语言的消息代码,消息描述保存在.msg结尾的文件,放在ros包的msg子目录。 rosmsg命令行工具打印消息定义信息,查找使用该消息的源文件 消息描述规范 .msg文件包含字段...


    参考:http://wiki.ros.org/msg

    ros使用一套简化的消息描述语言来描述ros节点所发布的数据。ros工具可以根据消息描述为消息类型生成不同目标语言的消息代码,消息描述保存在.msg结尾的文件,放在ros包的msg子目录。

    rosmsg命令行工具打印消息定义信息,查找使用该消息的源文件

    消息描述规范

    .msg文件包含字段常量两部分。

    一个字段由字段类型和字段名组成,

    字段

    fieldtype1 fieldname1
    fieldtype2 fieldname2
    fieldtype3 fieldname3
    

    如:

    int32 x
    int32 y
    

    字段类型

    类型可以是

    • 内置类型,如float32,string,

    • 也可以是自定义类型,geometry_msgs/PoseStamped。

    • 还可以是上面类型的固定或者可变长度的数组/列表。

    “float32[] ranges” or “Point32[10] points”

    • 头文件类型

    实际上自定义数据类型是由内置类型组成。

    内置类型:

    Primitive Type Serialization C++ Python2 Python3
    bool (1) unsigned 8-bit int uint8_t (2) bool
    int8 signed 8-bit int int8_t int
    uint8 unsigned 8-bit int uint8_t int (3)
    int16 signed 16-bit int int16_t int
    uint16 unsigned 16-bit int uint16_t int
    int32 signed 32-bit int int32_t int
    uint32 unsigned 32-bit int uint32_t int
    int64 signed 64-bit int int64_t long int
    uint64 unsigned 64-bit int uint64_t long int
    float32 32-bit IEEE float float float
    float64 64-bit IEEE float double float
    string ascii string (4) std::string str bytes
    time secs/nsecs unsigned 32-bit ints ros::Time rospy.Time
    duration secs/nsecs signed 32-bit ints ros::Duration rospy.Duration

    数组类型的原型

    Array Type Serialization C++ Python2 Python3
    fixed-length no extra serialization 0.11+: boost::array<T, length>, otherwise: std::vector<T> tuple (1)
    variable-length uint32 length prefix std::vector<T> tuple (1)
    uint8[] see above as above str bytes (2)
    bool[] see above std::vector<uint8_t> list of bool

    上表的意思是说,可变长度的类型,比如T,那么其数组类型,在C++里的底层实现是std::vector<T>,即类型为T的vector,其他类似。

    字段名

    字段名会变成目标语言访问消息数据的名字。例如后面学习的std_msgs下的各种内置类型,它的字段名就是data,所以我们在访问该类型的数据时,假如该消息对象叫obj,那么就是obj,data。

    只能是字母数字下划线。

    常量

    constanttype1 CONSTANTNAME1=constantvalue1
    constanttype2 CONSTANTNAME2=constantvalue2
    

    例如:

    int32 X=123
    int32 Y=-123
    string FOO=foo
    string EXAMPLE="#comments" are ignored, and leading and trailing whitespace removed
    

    整型数赋值只能是10进制。

    string类型常量所有空格都会被自动移除。

    编译消息文件

    package.xml加上以下两句:

    <build_depend>message_generation</build_depend>
    <run_depend>message_runtime</run_depend>
    

    一个是构建依赖,一个是运行依赖。

    导出消息运行依赖:

    catkin_package(
      ...
      CATKIN_DEPENDS message_runtime ...
      ...)
    

    添加你自己的消息文件:

    add_message_files(
       FILES
       Message1.msg
       Message2.msg
    )
    

    添加你的消息所依赖的消息:

     generate_messages(
       DEPENDENCIES
       std_msgs
    )
    

    关于std_msgs

    ros利用ros内置类型定义了一系列消息类型,这就是std_msgs,它们的字段名都叫data,这在链接可以查找。

    消息文件:
    https://github.com/ros/std_msgs

    展开全文
  • 2.在msg文件夹中定义创建消息obstacleMsg.msg(一定要以”.msg”结尾),并定义消息类型. int32[4] data int32[4] data2 int32[4] data3 3.添加编译支持(如果使用RoboWare Studio编写ROS代码时,以下依赖项可能已经被...

    基本流程

    1.在程序中创建msg文件夹,与src同一级别
    2.在msg文件夹中定义创建消息obstacleMsg.msg(一定要以”.msg”结尾),并定义消息类型.

    int32[4] data
    int32[4] data2
    int32[4] data3

    3.添加编译支持(如果使用RoboWare Studio编写ROS代码时,以下依赖项可能已经被自动生成,注意不要重复添加,建议检查一遍将没有的添加上)

    3.1.package.xml需要添加编译依赖项和运行依赖项

    <build_depend>message_generation</build_depend>
    <run_depend>message_runtime</run_depend>

    3.2.CmakeList.txt
    find_package()中添加message_generation

    find_package(catkin REQUIRED COMPONENTS
      message_generation
      roscpp
      rospy
      std_msgs
    )

    add_message_files()中添加can_data.msg

    add_message_files(FILES
      obstacleMsg.msg
    )

    generate_messages()去掉注释

    generate_messages(DEPENDENCIES
      std_msgs
    )

    catkin_package()添加message_runtime

    catkin_package(
      CATKIN_DEPENDS
      message_runtime)

    4.至此已经完成了自定义消息的过程,可以在命令框中输入catkin_make进行编译检查,修改过”.msg”文件后记得重新cmake.
    使用ROSWare Studio编译的用户可以点击左上角的绿色小斧头编译

    5.使用方法
    在需要使用的”.cpp”文件中添加

    #include <rplidar_ros/obstacleMsg.h>

    其中rplidar_ros是消息文件夹msg或该消息所在的ROS包的名字,obstacleMsg.h是消息的名字对应的”.h”文件

    使用时要按照下面格式定义变量

    rplidar_ros::obstacleMsg obstacle;

    其中rplidar_ros是消息文件夹msg或该消息所在的ROS包的名字,obstacleMsg是消息的名字,obstacle是根据自定义消息类型定义的变量

    定义后按照下面方法赋值使用

    obstacle.data = 0x01;

    常见错误以及解决方案

    1.遇到以下错误

    ...
      Invoking generate_messages() without having added any message or service
      file before.
    
      You should either add add_message_files() and/or add_service_files() cal
    ls
      or remove the invocation of generate_messages().
    ...
    -- Configuring incomplete, errors occurred!
    ...
    Makefile:1396: recipe for target 'cmake_check_build_system' failed
    make: *** [cmake_check_build_system] Error 1
    Invoking "make cmake_check_build_system" failed

    注意消息提示

    Invoking generate_messages() without having added any message or service
      file before.

    说明你没有在CMakeLists.txt文件中定义如下消息.

    add_message_files(FILES
      obstacleMsg.msg
    )
    
    generate_messages(DEPENDENCIES
      std_msgs
    )

    2.如果遇到以下错误

    CMake Error at /opt/ros/kinetic/share/genmsg/cmake/genmsg-extras.cmake:98
    (message):
      generate_messages() must be called after add_message_files()
    Call Stack (most recent call first):

    add_message_files()generate_messages()顺序出错,一定要按照以下顺序定义

    add_message_files(FILES
      obstacleMsg.msg
    )
    
    generate_messages(DEPENDENCIES
      std_msgs
    )

    3.如果遇到以下错误

    CMake Error at /opt/ros/kinetic/share/genmsg/cmake/genmsg-extras.cmake:197
     (message):
      generate_messages() must be called before catkin_package() in project
      'rplidar_ros'

    generate_messages()catkin_package()顺序出错,一定要按照以下顺序定义

    add_message_files(FILES
      obstacleMsg.msg
    )
    
    generate_messages(DEPENDENCIES
      std_msgs
    )
    
    catkin_package(
      CATKIN_DEPENDS
      message_runtime)

    综上,函数定义顺序很重要!!!

    展开全文
  • 基于Java自身技术实现消息方式的系统间通信基于Java自身包实现消息方式的系统间通信的方式有:TCP/IP+BIO、TCP/IP+NIO、UDP/IP+BIO以及UDP/IP+NIO 4种,下面分别介绍如何实现这4种方式的系统间通信。TCP/IP+BIO在...
  • 图文上传功能相对独立,因此在项目其他子系统完成之后增加这部分功能,看似简单的功能,测试时出现了“MIME 多节流出现意外的结尾。MIME 多节消息不完整”错误,问度娘,木有类似问题,谷哥之,“Unexpected end of ...
  • 阿里云常见用法及错误: 1、往阿里云上推消息,和从阿里云上拉取消息都需要本地服务器时间与阿里云上实际时间一致,也就是不能改时间。改时间会报超时的错误。 错误码:TimeExpired 错误描述:The ...
  • SOAP消息的传递

    千次阅读 2015-05-11 14:53:29
    上一篇说了SOAP消息的创建,那么创建好了的SOAP消息要怎么发送给服务端呢?public class SoapTest { private String wsdlUri = "http://localhost:9999/ns?wsdl"; private String ns = "http://lenve.server/"; @...
  • Akka框架的小结尾

    千次阅读 2012-08-21 20:22:55
    Akka框架,总的来说是一种比较好的框架,虽然接触它才没多长时间,现在又要暂时性的不再使用,但是其actor模式的应用却留下了深刻...再加上其对消息队列处理时的事务性,你不必担心有的消息发过来之后还会有被别的代码
  • 我的Oracle数据库是去年11月份安装的,然后安装好之后配置了一下,那个时候是正常的,没有什么问题,但是...提示ORA-03113:通信通道的文件结尾 进程 ID :0 会话 ID:0 序列号:0之后就是一系列的度娘谷歌论坛等等折腾
  • XMPP系列(四)---发送和接收文字消息,获取历史消息功能
  • 最近在整公司的QQ机器人开发,我们开发用到的是酷Q,用到的开发工具则是JCQ,然后因为对于图片或者文件消息等,接收到的字符串形如以下: [CQ:image,file=50CB70BF5232E82C5E0D73184FAAE3EB.jpg]广东省方法[CQ:...
  • Golang和Erlang消息传递机制对比

    千次阅读 2015-12-11 15:25:22
    本文将简要介绍这两种并发语言的消息传递机制简要对比Erlang和Go虽然在实现及功能上差异较大,但是都支持高并发的轻量级用户任务(Erlang的轻量进程,Go的Goroutine), 并且都采用了消息传递的方式作为任务间交互的...
  • ORA-03113:通信通道的文件结尾

    千次阅读 2018-11-30 16:09:03
    首先看下报错情况,返回消息 “ORA-03113” 解决思路:ORA-03113主要原因是因为表空间的使用率较高导致,我们的目标是降低使用率。 (1)、查看系统表空间用量,会发现SYSAUX/SYSTEM表空间的使用率较高 SELECT...
  • struts 中就使用了这个包,不过是用 struts 的方式另行封装了一次。这里我们直接使用 fileupload 包。至于struts 中的用法,请参阅 struts 相关文档。 这个处理文件上传的 servelet 主要代码如下: ...
  • 模板消息接口文档

    千次阅读 2014-08-29 11:07:07
    为了保证用户不受到骚扰,在开发者出现需要主动提醒、通知用户时,才允许开发者在公众...1.模板中参数内容必须以".DATA"结尾,否则视为保留字; 2.模板保留符号"{{ }}" 具体调用方法 第一步:获取模板ID 通过在模板
  • 消息队列RabbitMQ的整理总结

    万次阅读 2019-03-19 18:54:49
    现在实现MQ的有两种主流方式:AMQP、JMS。 正如上图所说,队列的使用除去了接受和发送应用程序同时执行的要求,消息队列是典型的:生产者、消费者模型。生产者不断向消息队列中生产消息,消费者不断的从队列中获取...
  • 微信小程序订阅消息

    千次阅读 热门讨论 2020-03-02 15:19:21
    消息能力是小程序能力中的重要组成,以便实现服务的闭环和更优的体验。此前的小程序模板消息接口于2020年1月10日下线,2.10.0 版本开始,开发版和体验版小程序将禁止使用模板消息 fomrId。开发者可使用订阅消息功能...
  • 在上一篇博文中,我们已经学习过了消息处理机制的基础,对这个过程所涉及到的几个重要的类也有了一定的了解,如果在这方面不清楚也没看过上一篇博文的读者,请点击先阅读《 Android开发知识(五)消息处理机制的基础...
  • F12 开发人员工具控制台错误消息

    万次阅读 2015-07-24 10:09:04
    F12 工具控制台可以报告在运行时期间发生的错误和信息消息。本文将介绍错误消息,并提供有关如何修正这些错误的建议。 简介 F12 工具控制台错误消息提供了一些代码(例如,SEC7111 或 HTML1114),这些代码...
  • CSDN地址:... ... DBus一个简易、高效的消息框架。没看过EventBus的源码,但是个人感觉此项目够简洁高效、易懂易用! DBus项目突出的特点: 1、注册消息事件的类可以是
  • netty实战-自定义解码器处理半包消息

    万次阅读 热门讨论 2017-09-10 10:29:23
    ByteToMessageDecoder这两个解码器来处理业务消息。但是有时候为了灵活性,会直接选择继承ByteToMessageDecoder来处理业务消息,但是直接继承ByteToMessageDecoder,则需要自己处理半包问题。在李林锋的【netty
  • 消息驱动bean来处理本地的JMS消息太容易不过了,但是如何处理...把下面的代码复制到一个文件里,并重名为以-service.xml结尾的文件,放到jboss的deploy目录,就可以在本地得到一个从远程获取消息的JMS provider。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 97,516
精华内容 39,006
关键字:

常见的消息结尾方式