zoukankan      html  css  js  c++  java
  • Netty解决粘包问题

    知识点

    1、看下粘包和分包是怎么样一个情况
      hello hello
      通过定义一个稳定的结构 length + hello
    
    2、buffer里面数据未被读取完怎么办?    (cumulation缓存)
    
    3、为什么return null就可以缓存buffer     (cumulation缓存)

    1、Client.java

    package com.example.netty.lesson11.packet;
    
    import java.net.Socket;
    import java.nio.ByteBuffer;
    
    public class Client {
    
        public static void main(String[] args) throws Exception {
            /**
             * 会出现粘包现象,通过ByteBuffer解决粘包问题
             */
            Socket socket = new Socket("127.0.0.1", 51503);
    
            String message = "hello,ni hao ma?";
            byte[] bytes = message.getBytes();
            //4定义为包头位数
            ByteBuffer buffer = ByteBuffer.allocate(4+bytes.length);
            buffer.putInt(bytes.length);
            buffer.put(bytes);
    
            byte[] array = buffer.array();
            for (int i = 0; i <1000 ; i++) {
                socket.getOutputStream().write(array);
            }
    
            socket.close();
        }
    
    }

    2、Server.java

    package com.example.netty.lesson11.packet;
    
    import com.example.netty.lesson11.pipeLine.MyHandler2;
    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 bootstrap = new ServerBootstrap();
            
            //boss线程监听端口,worker线程负责数据读写
            ExecutorService boss = Executors.newCachedThreadPool();
            ExecutorService worker = Executors.newCachedThreadPool();
            
            //设置niosocket工厂
            bootstrap.setFactory(new NioServerSocketChannelFactory(boss, worker));
            
            //设置管道的工厂
            bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
                
                @Override
                public ChannelPipeline getPipeline() throws Exception {
    
                    ChannelPipeline pipeline = Channels.pipeline();
                    pipeline.addLast("decoder", new MyDecoder());
                    pipeline.addLast("handler1", new MyHandler1());
                    return pipeline;
                }
            });
            
            bootstrap.bind(new InetSocketAddress(51503));
            
            System.out.println("start!!!");
        }
    
    }

    3、MyDecoder.java

    package com.example.netty.lesson11.packet;
    
    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;
    
    /**
     * @author yangwj
     * @date 2020/4/6 10:48
     */
    public class MyDecoder extends FrameDecoder {
        @Override
        protected Object decode(ChannelHandlerContext channelHandlerContext, Channel channel, ChannelBuffer buffer) throws Exception {
            if(buffer.readableBytes() >4){
                //标记
                buffer.markReaderIndex();
                //长度
                int length = buffer.readInt();
                if(buffer.readableBytes() < length){
                    buffer.resetReaderIndex();
                    //缓存当前剩余的buffer数据,等待剩下的数据到来
                    return null;
                }
                //读数据
                byte[] bytes = new byte[length];
                buffer.readBytes(bytes);
                //往下传递 ,和sendUpstream类似
                return  new String(bytes);
            }
            //缓存当前剩余的buffer数据,等待剩下的数据到来
            return null;
        }
    }

    4、MyHandler1.java

    package com.example.netty.lesson11.packet;
    
    import org.jboss.netty.channel.ChannelHandlerContext;
    import org.jboss.netty.channel.MessageEvent;
    import org.jboss.netty.channel.SimpleChannelHandler;
    
    public class MyHandler1 extends SimpleChannelHandler {
    
        @Override
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    
    //        ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
    //
    //        byte[] array = buffer.array();
    //        String message = new String(array);
            String message = (String) e.getMessage();
            System.out.println("handler1:" + message);
    
        }
    }

    完毕!

  • 相关阅读:
    解决Shiro在Tomcat重启之后丢失登录信息
    代码安全审计大全
    解决Spring Boot打包war部署到Tomcat出现Could not open ServletContext resource
    weblogic12 重装记录
    【Spring】事物和锁及回滚异常类型
    【Spring】thymeleaf + SpringMVC局部刷新
    【Spring】@ModelAttribute三种使用场景
    Java Optional
    JAVA lambda
    最短时间(最短路+思维)
  • 原文地址:https://www.cnblogs.com/ywjfx/p/12812995.html
Copyright © 2011-2022 走看看