短連結
傳送資料後斷開連線,下次傳送時重新建立連線
// Client端 public static void main (String[] args) { for (int i = 0; i < 10; i++) { send(); } } // 傳送資料 public void send () { NioEventLoopGroup worker = new NioEventLoopGroup(); try { new Bootstrap().channel(NioSocketChannel.class) .group(worker) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { // channel連線建立好後觸發 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { for (int i = 0; i < 10; i++) { ByteBuf buf = ctx.alloc().buffer(16); buf.writeBytes(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}); ctx.writeAndFlush(buf); // 傳送完畢斷開連線 ctx.channel().close(); } } }); } }).connect("127.0.0.1", 8080).sync() .channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { worker.shutdownGracefully(); } }
定長解碼器
在客戶端傳送的資料長度固定時將服務端的解碼器設定為定長解碼器
FixedLengthFrameDecoder
可避免粘包和半包的問題// Server端 try { new ServerBootstrap() .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_RCVBUF, 10) .group(new NioEventLoopGroup(1), new NioEventLoopGroup()); .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("decoder", new FixedLengthFrameDecoder(Demo2Client.LENGTH)); ch.pipeline().addLast("logging", new LoggingHandler(LogLevel.DEBUG)); } }) .bind(8080).sync().channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }
行解碼器
行解碼器``就是服務端在解析客戶端傳送的資料時將固定的字元
\n
作為一個資料包的分隔符進行解析// Server端 try { new ServerBootstrap() .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_RCVBUF, 10) .group(new NioEventLoopGroup(1), new NioEventLoopGroup()); .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("line", // 引數位一行資料的最大長度 new LineBasedFrameDecoder(1024)); ch.pipeline().addLast("logging", new LoggingHandler(LogLevel.DEBUG)); } }) .bind(8080).sync().channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }
LTC解碼器
原始碼案例
引數解釋:
- maxFrameLength: 一條資料的最大長度
- lengthFieldOffset: 長度欄位的偏移量
- lengthFieldLength: 長度欄位所佔的位元組數
- lengthAdjustment: 在長度欄位和資料欄位之間插入的附加欄位的所佔位元組數
- initialBytesToStrip: 解碼後剝離的位元組數
LengthFieldBasedFrameDecoder
的建構函式public LengthFieldBasedFrameDecoder( int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) { ...... }
演示案例
public static void main(String[] args) { EmbeddedChannel channel = new EmbeddedChannel( new LengthFieldBasedFrameDecoder(512, 5, 4, 1, 10), new LoggingHandler(LogLevel.DEBUG) ); ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(); send(buf, "Hello, World"); send(buf, "Hi"); channel.writeInbound(buf); } // 傳送方法 private static void send (ByteBuf buf, String content) { byte[] header = "NETTY".getBytes(); byte[] bytes = content.getBytes(); int length = bytes.length; buf.writeBytes(header); buf.writeInt(length); buf.writeByte(1); buf.writeBytes(bytes); }
本作品採用《CC 協議》,轉載必須註明作者和本文連結