zoukankan      html  css  js  c++  java
  • netty之粘包分包的处理

      1、netty在进行字节数组传输的时候,会出现粘包和分包的情况。当个数据还好,如果数据量很大。并且不间断的发送给服务器,这个时候就会出现粘包和分包的情况。

      2、简单来说:channelBuffer在接收包的时候,会在当时进行处理,但是当数据量一大,这个时候数据的分隔就不是很明显了。这个时候会出现数据多了或者少了的情况

      3、处理的方式,一般就是编解码。自己定义数据:数据长度+数据。这种简单的方式来实现。在server进行解密操作。

      4、一般规定的数据格式必须包含:包头+长度+数据(包头的目的是用来判断数据是否是开始的时候)

      5、具体的实现过程

      a、客户端进行编码

    package com.troy.application.buffer;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SocketChannel;
    
    public class Client {
    
        public static void main(String[] args) {
            try {
                SocketChannel socketChannel = SocketChannel.open();
                socketChannel.connect(new InetSocketAddress("localhost",9000));
                //需要发送的数据
                String message = "hello";
                //这里的4代表message的长度所占字节
                ByteBuffer byteBuffer = ByteBuffer.allocate(4+message.length());
                //设置数据
                byteBuffer.putInt(message.length());
                byteBuffer.put(message.getBytes());
                //写出数据
                socketChannel.write(ByteBuffer.wrap(byteBuffer.array()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

      b、服务端

    package com.troy.application.buffer;
    
    import org.jboss.netty.bootstrap.ServerBootstrap;
    import org.jboss.netty.channel.ChannelPipeline;
    import org.jboss.netty.channel.ChannelPipelineFactory;
    import org.jboss.netty.channel.Channels;
    import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
    
    import java.net.InetSocketAddress;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Server {
    
        public static void main(String[] args) {
    
            //声明服务类
            ServerBootstrap serverBootstrap = new ServerBootstrap();
    
            //设定线程池
            ExecutorService boss = Executors.newCachedThreadPool();
            ExecutorService work = Executors.newCachedThreadPool();
    
            //设置工厂
            serverBootstrap.setFactory(new NioServerSocketChannelFactory(boss,work));
    
            //设置管道流
            serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
                @Override
                public ChannelPipeline getPipeline() throws Exception {
                    ChannelPipeline channelPipeline = Channels.pipeline();
                    //添加处理方式
                    channelPipeline.addLast("decode",new PackageDecoder());
                    channelPipeline.addLast("hello",new HelloHandler());
                    return channelPipeline;
                }
            });
            //设置端口
            serverBootstrap.bind(new InetSocketAddress(9000));
        }
    }

      c、解码

    package com.troy.application.buffer;

    import org.jboss.netty.buffer.ChannelBuffer;
    import org.jboss.netty.channel.Channel;
    import org.jboss.netty.channel.ChannelHandlerContext;
    import org.jboss.netty.handler.codec.frame.FrameDecoder;

    public class PackageDecoder extends FrameDecoder {


    @Override
    protected Object decode(ChannelHandlerContext channelHandlerContext, Channel channel, ChannelBuffer channelBuffer) throws Exception {
    if (channelBuffer.readableBytes() > 4) {
    //标记读取位置
    channelBuffer.markReaderIndex();
    //读取数据长度
    int n = channelBuffer.readInt();
    if (channelBuffer.readableBytes() < n) {
    //如果数据长度小于设定的数据,则处于缓存状态
    channelBuffer.resetReaderIndex();
    //缓存当前数据,等待数据接入
    return null;
    }
    byte[] bytes = new byte[n];
    channelBuffer.readBytes(bytes);
    return new String(bytes);
    }
    //缓存当前数据,等待数据接入
    return null;
    }
    }

      d、数据接收处理

    package com.troy.application.buffer;
    
    import org.jboss.netty.channel.ChannelHandlerContext;
    import org.jboss.netty.channel.MessageEvent;
    import org.jboss.netty.channel.SimpleChannelHandler;
    
    public class HelloHandler extends SimpleChannelHandler{
    
        @Override
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    
            System.out.println(e.getMessage());
        }
    }
  • 相关阅读:
    把打好的war包部署到虚拟机上,mysql数据库在本机上,启动后,网页查询不到数据,异常
    NAT模式下的虚拟机
    Jsp有四种属性范围和Jsp的九大内置对象
    Tomcat笔记
    视频编解码相关基础知识(一)----H.264编码和H.265编码的区别
    相机中的一些常见参数及相关概念
    Linux常用命令
    基于Linux的C编程(一)
    Shell程序设计
    Linux文本编辑器
  • 原文地址:https://www.cnblogs.com/ll409546297/p/8042802.html
Copyright © 2011-2022 走看看