说一下
粘包 客户端 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 package com.redisc;import io.netty.bootstrap.Bootstrap;import io.netty.buffer.ByteBuf;import io.netty.channel.*;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.handler .codec.string.StringEncoder;import io.netty.handler .logging.LogLevel;import io.netty.handler .logging.LoggingHandler;import lombok.extern.slf4j.Slf4j;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.IOException;import java.net.InetSocketAddress;public class Client { static final Logger log = LoggerFactory.getLogger(Client.class ) ; public static void main (String[] args) throws IOException, InterruptedException { NioEventLoopGroup worker = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.channel(NioSocketChannel.class ) ; bootstrap.group(worker); bootstrap.handler (new ChannelInitializer<SocketChannel>() { @Override protected void initChannel (SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() { @Override public void channelActive (ChannelHandlerContext ctx) throws Exception { for (int i = 0 ; i < 14 ; i++) { ByteBuf byteBuf = ctx.alloc().buffer(16 ); byteBuf.writeBytes(new byte []{1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }); ctx.writeAndFlush(byteBuf); } } }); } }); ChannelFuture channelFuture = bootstrap.connect("127.0.0.1" , 8000 ); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { log.error ("error" , e); } finally { worker.shutdownGracefully(); } } }
服务端 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package com.redisc;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler .logging.LogLevel;import io.netty.handler .logging.LoggingHandler;import lombok.extern.slf4j.Slf4j;import java.io.IOException;@Slf 4jpublic class Server { public static void main (String[] args) throws IOException { NioEventLoopGroup boss = new NioEventLoopGroup(); NioEventLoopGroup worker = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.channel(NioServerSocketChannel.class ) ; serverBootstrap.group(boss, worker); serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel (SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG)); } }); ChannelFuture channelFuture = serverBootstrap.bind(8000 ).sync(); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { log.error ("error" , e); } finally { boss.shutdownGracefully(); worker.shutdownGracefully(); } } }
服务端输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 11 :46 :53.302 [nioEventLoopGroup-3 -1 ] DEBUG io.netty.handler.logging.LoggingHandler - [id: 0xb6dbd17e , L:/127.0 .0 .1 :8000 - R:/127.0 .0 .1 :50839 ] READ: 126 B +-------------------------------------------------+ | 0 1 2 3 4 5 6 7 8 9 a b c d e f | +--------+-------------------------------------------------+----------------+ |00000000 | 01 02 03 04 05 06 07 08 09 01 02 03 04 05 06 07 |................| |00000010 | 08 09 01 02 03 04 05 06 07 08 09 01 02 03 04 05 |................| |00000020 | 06 07 08 09 01 02 03 04 05 06 07 08 09 01 02 03 |................| |00000030 | 04 05 06 07 08 09 01 02 03 04 05 06 07 08 09 01 |................| |00000040 | 02 03 04 05 06 07 08 09 01 02 03 04 05 06 07 08 |................| |00000050 | 09 01 02 03 04 05 06 07 08 09 01 02 03 04 05 06 |................| |00000060 | 07 08 09 01 02 03 04 05 06 07 08 09 01 02 03 04 |................| |00000070 | 05 06 07 08 09 01 02 03 04 05 06 07 08 09 |.............. | +--------+-------------------------------------------------+----------------+ 11 :46 :53.303 [nioEventLoopGroup-3 -1 ] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded inbound message PooledUnsafeDirectByteBuf(ridx: 0 , widx: 126 , cap: 2048 ) that reached at the tail of the pipeline. Please check your pipeline configuration.11 :46 :53.305 [nioEventLoopGroup-3 -1 ] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded message pipeline : [LoggingHandler#0 , DefaultChannelPipeline$TailContext#0 ]. Channel : [id: 0xb6dbd17e , L:/127.0 .0 .1 :8000 - R:/127.0 .0 .1 :50839 ].11 :46 :53.306 [nioEventLoopGroup-3 -1 ] DEBUG io.netty.handler.logging.LoggingHandler - [id: 0xb6dbd17e , L:/127.0 .0 .1 :8000 - R:/127.0 .0 .1 :50839 ] READ COMPLETE
虽然客户端是
1 2 3 4 5 for (int i = 0 ; i < 14 ; i++) { ByteBuf byteBuf = ctx.alloc().buffer(16 ); byteBuf.writeBytes(new byte[]{1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }); ctx.writeAndFlush(byteBuf); }
但是,服务端并不是一个个接收,而是一起接收。
半包 在服务端增加一句
serverBootstrap.option(ChannelOption.SO_RCVBUF,10);
即
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 package com.redisc;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler .logging.LogLevel;import io.netty.handler .logging.LoggingHandler;import lombok.extern.slf4j.Slf4j;import java.io.IOException;@Slf 4jpublic class Server { public static void main (String[] args) throws IOException { NioEventLoopGroup boss = new NioEventLoopGroup(); NioEventLoopGroup worker = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.channel(NioServerSocketChannel.class ) ; serverBootstrap.option(ChannelOption.SO_RCVBUF, 10 ); serverBootstrap.group(boss, worker); serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel (SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG)); } }); ChannelFuture channelFuture = serverBootstrap.bind(8000 ).sync(); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { log.error ("error" , e); } finally { boss.shutdownGracefully(); worker.shutdownGracefully(); } } }
这句话是把缓冲区大小设置为 10
。
但是,在 MacBook
中输出还是上面的输出。在 windowns
可以看到半包的情况,这是因为底层的操作系统使用的缓冲区逻辑不同。