netty 處理粘包的兩種方案

第一種方案  根據固定的字符標誌一條消息的結束(DelimiterBasedFrameDecoder)

實現代碼(這裏用 ## 來標誌一條消息的結束):

 ByteBuf buf = Unpooled.copiedBuffer("##".getBytes());
 sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));

第二種方案  根據固定長度標誌一條消息的結束(FixedLengthFrameDecoder)

實現代碼(一條消息的固定長度爲14):

 //2:根據固定長度標誌一條消息的結束
 sc.pipeline().addLast(new FixedLengthFrameDecoder(14));

完整代碼如下:

package com.netty.v0;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.ScheduledFuture;

import java.awt.*;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * \* Description:
 * \* Created with IntelliJ IDEA.
 * \* User: fdes
 * \* Date: 2018/8/24
 * \* Time: 11:47
 * \
 */
public class Server {
    public static void main(String[] args) throws InterruptedException {

        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup work = new NioEventLoopGroup();

        ServerBootstrap sb = new ServerBootstrap();
        sb.group(boss,work)
                .channel(NioServerSocketChannel.class)
                .childOption(ChannelOption.SO_KEEPALIVE,true)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel sc) throws Exception {
                        //1:根據固定的字符標誌一條消息的結束
                        //ByteBuf buf = Unpooled.copiedBuffer("##".getBytes());
                        //sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));


                        //2:根據固定長度標誌一條消息的結束
                        //sc.pipeline().addLast(new FixedLengthFrameDecoder(14));

                        //3:也可以直接發送字符串,客戶端需要添加字符串編碼器,服務器端需要添加解碼器
                        sc.pipeline().addLast(new StringDecoder());
                        sc.pipeline().addLast(new ServerHandler());
                    }
                });

        ChannelFuture cf = sb.bind(8888).sync();

        cf.channel().closeFuture().sync();
        work.shutdownGracefully();
        boss.shutdownGracefully();
    }
}
package com.netty.v0;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * \* Description:
 * \* Created with IntelliJ IDEA.
 * \* User: fdes
 * \* Date: 2018/8/24
 * \* Time: 17:02
 * \
 */
public class ServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("=================channelRegistered=============================" + ctx.channel().id());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("=================channelActive=============================" + ctx.channel().id());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("=================channelRead=============================" + ctx.channel().id());

       ByteBuf bb = (ByteBuf) msg;
        byte[] bytes = new byte[bb.readableBytes()];
        bb.readBytes(bytes);
        System.out.println("收到客戶端數據:" + new String(bytes));
        ctx.writeAndFlush(Unpooled.copiedBuffer("你好,已經收到你的消息。我是服務器".getBytes()));

      /* 測試直接收字符串消息代碼
      String str = (String)msg;
       System.out.println(str);*/
    }


}
package com.netty.v0;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
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.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * \* Description:
 * \* Created with IntelliJ IDEA.
 * \* User: fdes
 * \* Date: 2018/8/24
 * \* Time: 17:02
 * \
 */
public class Client {
    public static void main(String[] args) throws InterruptedException {

        EventLoopGroup work = new NioEventLoopGroup();

        Bootstrap sb = new Bootstrap();
        sb.group(work)
        .channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new StringEncoder());
                ch.pipeline().addLast(new ClientHandler());
            }
        });

        ChannelFuture cf = sb.connect("127.0.0.1",8888).sync();

        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty1##".getBytes()));
        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty2##".getBytes()));
        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty3##".getBytes()));
        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty4##".getBytes()));
        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty5##".getBytes()));
        cf.channel().writeAndFlush(Unpooled.copiedBuffer("hello netty6##".getBytes()));


        //測試直接發送字符串消息
        //cf.channel().writeAndFlush("你好我來了,我是字符串!!!");

        cf.channel().closeFuture().sync();
        work.shutdownGracefully();
    }
}
package com.netty.v0;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * \* Description:
 * \* Created with IntelliJ IDEA.
 * \* User: fdes
 * \* Date: 2018/8/24
 * \* Time: 17:24
 * \
 */
public class ClientHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("=================channelRead=============================" + ctx.channel().id());
        ByteBuf bb = (ByteBuf) msg;
        byte[] bytes = new byte[bb.readableBytes()];
        bb.readBytes(bytes);
        System.out.println("收到服務器數據:" + new String(bytes));
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章