Netty中半包粘包的产生与处理:短连接、固定长度、固定分隔符、预设长度;redis、http协议举例;网络数据的发送和接收过程

目录

粘包、半包

相关概念

网络数据发送和接收过程

Netty半包粘包解决方案

ByteBuf获取和默认大小

短链接

固定长度

固定分隔符

预设长度 

常见协议代码举例

redis协议

http协议 

 参考链接

粘包、半包

相关概念

        程序处理过程中我们会通过缓冲区接收数据,接收的过程中可能会出现所谓的粘包和半包的问题。

        当发送方发送数据大小小于接收方缓冲区大小且接收方来不及处理缓冲区中的内容,此时可能发生发送方发送多个完整的消息到接收方缓冲区中,接收方误将其作为一次发送的消息处理,此时产生粘包现象。

        当发送方数据大小大于接收方缓冲区大小时,发送方数据并不能一次全部发送到接收方缓冲区中,此时发送方数据就会被拆分为不同的数据大小进行发送,此时产生半包现象。

网络数据发送和接收过程

        通信过程有一个客户端和一个接收端,站在客户端角度来讲,我们可以分为这样的几个层次,用户区或者叫用户态,系统区或者内核区或者叫内核态,再往下是硬件或则叫网卡。

        Java程序是在用户区,socketChnnel.write(byte)这个时候就是把数据复制到我们的内核态当中,然后操作系统将数据再次拷贝给网卡,网卡操作数据可以传递出去。真正发送的时候会以数据包的形式进行发送,当然数据包的这个概念是不准确的,应该叫做数据帧。
        接收方数据拿到之后,由网卡拿到数据之后将数据拷贝到操作系统的数据的缓冲区,也就是socket的缓冲区,当我们调用一些读的方法的时候,Socket缓冲区的数据会拷贝到我们的用户区里边。

        用户内存和我们的Socket的缓冲区这两个都有可能产生一个半包粘包的问题(数据要么存少了,要么存多了)

        DMA(Direct Memory Access)直接内存访问,是一种计算机硬件特性,允许某些硬件设备(磁盘驱动器、网络接口卡等)直接向内存传输数据,而不需要中央处理器CPU的介入。能够显著提高数据传输的效率,能够减少CPU负载,允许CPU在数据传输期间执行其他任务。

Netty半包粘包解决方案

        粘包:是由于数据发送太快,接收方byteBuf太大。

        半包:MSS、接收方byteBuf太小。

ByteBuf获取和默认大小

        ByteBuf是Netty通过Handler帮我们创建的(第一个非head的InboundHandler获取的参数就是Netty获取的数据),Netty接收数据帮我们创建的ByteBuf的大小默认是1024B,可以指定最小字节16,同时也可以指定(最小值、初始值、最大值)。

        我们可以人为地设置Socket缓冲区和ByteBuf缓冲区,从而更好地验证Netty在网络传输中出现的半包、粘包现象以及其解决方案。

        Soket缓冲区的改变是一个全局的概念。ChannelOption.SO_REVBUF代表的是接收缓冲区的大小。channelOption.SO_SNDBUF代表的是发送缓冲区的大小。SO代表的是Socket,通过这种方式所做的修改是在应用程序层面做出的修改,不会上升到全局的角度,这样不会影响到操作系统下其他的TCP协议通信的程序。

短链接

        短链接:发一个包建立一个连接,这样连接建立到断开之间就是消息边界。人为的让连接建立和断开,连接断开后服务端读取到的消息长度为-1,此时服务器端就知道客户端断开,读取的消息为一次完整的消息。

        局限性:发一次包建立一次连接,效率太低;短连接能够解决粘包问题,当ByteBuf太小时,对于半包的处理无能为力。

        服务器端代码:

@Slf4j
public class HelloServer {public static void main(String[] args) {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>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));}});ChannelFuture channelFuture = serverBootstrap.bind(8080).sync();channelFuture.channel().closeFuture().sync();} catch (InterruptedException e) {log.error("Server error ", e);} finally {boss.shutdownGracefully();worker.shutdownGracefully();}}
}

        客户端代码:

public class HelloClient {static final Logger log = LoggerFactory.getLogger(HelloClient.class);public static void main(String[] args) {for (int i = 0; i < 10; i++) {send();}}private static void send() {NioEventLoopGroup worker = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(worker);bootstrap.channel(NioSocketChannel.class);bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){// channelActive会在连接channel建立成功后,会触发 active事件@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ByteBuf buffer = ctx.alloc().buffer(10);buffer.writeBytes(new byte[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15});ctx.writeAndFlush(buffer);ctx.channel().close();}});}});ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress("localhost", 8080));channelFuture.channel().closeFuture().sync();} catch (Exception e) {log.info("clinet error ", e);} finally {worker.shutdownGracefully();}}
}

        结果:

00:01:43.237 [nioEventLoopGroup-3-8] INFO io.netty.handler.logging.LoggingHandler - [id: 0x700958ce, L:/127.0.0.1:8080 - R:/127.0.0.1:62462] READ COMPLETE
00:01:43.237 [nioEventLoopGroup-3-8] INFO io.netty.handler.logging.LoggingHandler - [id: 0x700958ce, L:/127.0.0.1:8080 - R:/127.0.0.1:62462] READ COMPLETE
00:01:43.237 [nioEventLoopGroup-3-8] INFO io.netty.handler.logging.LoggingHandler - [id: 0x700958ce, L:/127.0.0.1:8080 ! R:/127.0.0.1:62462] INACTIVE
00:01:43.238 [nioEventLoopGroup-3-8] INFO io.netty.handler.logging.LoggingHandler - [id: 0x700958ce, L:/127.0.0.1:8080 ! R:/127.0.0.1:62462] UNREGISTERED
00:01:43.255 [nioEventLoopGroup-3-9] INFO io.netty.handler.logging.LoggingHandler - [id: 0xc73537e9, L:/127.0.0.1:8080 - R:/127.0.0.1:62591] REGISTERED
00:01:43.256 [nioEventLoopGroup-3-9] INFO io.netty.handler.logging.LoggingHandler - [id: 0xc73537e9, L:/127.0.0.1:8080 - R:/127.0.0.1:62591] ACTIVE
00:01:43.268 [nioEventLoopGroup-3-9] INFO io.netty.handler.logging.LoggingHandler - [id: 0xc73537e9, L:/127.0.0.1:8080 - R:/127.0.0.1:62591] READ: 16B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
+--------+-------------------------------------------------+----------------+
00:01:43.268 [nioEventLoopGroup-3-9] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded inbound message SimpleLeakAwareByteBuf(PooledUnsafeDirectByteBuf(ridx: 0, widx: 16, cap: 1024)) that reached at the tail of the pipeline. Please check your pipeline configuration.
00:01:43.268 [nioEventLoopGroup-3-9] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded message pipeline : [LoggingHandler#0, DefaultChannelPipeline$TailContext#0]. Channel : [id: 0xc73537e9, L:/127.0.0.1:8080 - R:/127.0.0.1:62591].
00:01:43.268 [nioEventLoopGroup-3-9] INFO io.netty.handler.logging.LoggingHandler - [id: 0xc73537e9, L:/127.0.0.1:8080 - R:/127.0.0.1:62591] READ COMPLETE
00:01:43.268 [nioEventLoopGroup-3-9] INFO io.netty.handler.logging.LoggingHandler - [id: 0xc73537e9, L:/127.0.0.1:8080 - R:/127.0.0.1:62591] READ COMPLETE
00:01:43.268 [nioEventLoopGroup-3-9] INFO io.netty.handler.logging.LoggingHandler - [id: 0xc73537e9, L:/127.0.0.1:8080 ! R:/127.0.0.1:62591] INACTIVE
00:01:43.268 [nioEventLoopGroup-3-9] INFO io.netty.handler.logging.LoggingHandler - [id: 0xc73537e9, L:/127.0.0.1:8080 ! R:/127.0.0.1:62591] UNREGISTERED
00:01:43.285 [nioEventLoopGroup-3-10] INFO io.netty.handler.logging.LoggingHandler - [id: 0xcd634dbe, L:/127.0.0.1:8080 - R:/127.0.0.1:62720] REGISTERED
00:01:43.285 [nioEventLoopGroup-3-10] INFO io.netty.handler.logging.LoggingHandler - [id: 0xcd634dbe, L:/127.0.0.1:8080 - R:/127.0.0.1:62720] ACTIVE
00:01:43.298 [nioEventLoopGroup-3-10] INFO io.netty.handler.logging.LoggingHandler - [id: 0xcd634dbe, L:/127.0.0.1:8080 - R:/127.0.0.1:62720] READ: 16B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
+--------+-------------------------------------------------+----------------+
00:01:43.298 [nioEventLoopGroup-3-10] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded inbound message PooledUnsafeDirectByteBuf(ridx: 0, widx: 16, cap: 1024) that reached at the tail of the pipeline. Please check your pipeline configuration.
00:01:43.298 [nioEventLoopGroup-3-10] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded message pipeline : [LoggingHandler#0, DefaultChannelPipeline$TailContext#0]. Channel : [id: 0xcd634dbe, L:/127.0.0.1:8080 - R:/127.0.0.1:62720].
00:01:43.298 [nioEventLoopGroup-3-10] INFO io.netty.handler.logging.LoggingHandler - [id: 0xcd634dbe, L:/127.0.0.1:8080 - R:/127.0.0.1:62720] READ COMPLETE
00:01:43.298 [nioEventLoopGroup-3-10] INFO io.netty.handler.logging.LoggingHandler - [id: 0xcd634dbe, L:/127.0.0.1:8080 - R:/127.0.0.1:62720] READ COMPLETE
00:01:43.299 [nioEventLoopGroup-3-10] INFO io.netty.handler.logging.LoggingHandler - [id: 0xcd634dbe, L:/127.0.0.1:8080 ! R:/127.0.0.1:62720] INACTIVE
00:01:43.299 [nioEventLoopGroup-3-10] INFO io.netty.handler.logging.LoggingHandler - [id: 0xcd634dbe, L:/127.0.0.1:8080 ! R:/127.0.0.1:62720] UNREGISTERED

固定长度

        固定长度首先约定发送方发送的所有数据包长度固定,均为一个常量,随后接收方借助定长解码器【FixedLengthFrameDecoder】解析获取到的定长消息。

         FixedLengthFrameDecoder:接收方收到数据后首先将其缓存起来,随后提取固定长度后解码处理。

        可以通过如下命令设置接收方的定长解码器:

socketChannel.pipeline().addLast(new FixedLengthFrameDecoder(10));

        服务端代码:

@Slf4j
public class HelloServer {public static void main(String[] args) {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>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new FixedLengthFrameDecoder(10));socketChannel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));}});ChannelFuture channelFuture = serverBootstrap.bind(8080).sync();channelFuture.channel().closeFuture().sync();} catch (InterruptedException e) {log.error("Server error ", e);} finally {boss.shutdownGracefully();worker.shutdownGracefully();}}
}

        客户端代码:

public class HelloClient {static final Logger log = LoggerFactory.getLogger(HelloClient.class);public static void main(String[] args) {send();}private static byte[] fillChar(char ch, int lenght){byte[] ans = new byte[10];Arrays.fill(ans, (byte) '_');for(int i = 0; i < lenght; i++){ans[i] = ((byte) ch);}for (int i = 0; i < ans.length; i++) {System.out.print((char) ans[i]);}System.out.println();return ans;}private static void send() {NioEventLoopGroup worker = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(worker);bootstrap.channel(NioSocketChannel.class);bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){// channelActive会在连接channel建立成功后,会触发 active事件@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ByteBuf buffer = ctx.alloc().buffer(10);for (int i = 0; i < 10; i++) {char ch = (char) ('a' + i);buffer.writeBytes(fillChar(ch, i + 1));
//                                ctx.channel().close();}ctx.writeAndFlush(buffer);}});}});ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress("localhost", 8080));channelFuture.channel().closeFuture().sync();} catch (Exception e) {log.info("clinet error ", e);} finally {worker.shutdownGracefully();}}
}

        结果: 

00:10:24.650 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded inbound message PooledSlicedByteBuf(ridx: 0, widx: 10, cap: 10/10, unwrapped: PooledUnsafeDirectByteBuf(ridx: 40, widx: 100, cap: 1024)) that reached at the tail of the pipeline. Please check your pipeline configuration.
00:10:24.650 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded message pipeline : [FixedLengthFrameDecoder#0, LoggingHandler#0, DefaultChannelPipeline$TailContext#0]. Channel : [id: 0x4824e86f, L:/127.0.0.1:8080 - R:/127.0.0.1:64332].
00:10:24.650 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x4824e86f, L:/127.0.0.1:8080 - R:/127.0.0.1:64332] READ: 10B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 65 65 65 65 65 5f 5f 5f 5f 5f                   |eeeee_____      |
+--------+-------------------------------------------------+----------------+
00:10:24.650 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded inbound message PooledSlicedByteBuf(ridx: 0, widx: 10, cap: 10/10, unwrapped: PooledUnsafeDirectByteBuf(ridx: 50, widx: 100, cap: 1024)) that reached at the tail of the pipeline. Please check your pipeline configuration.
00:10:24.650 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded message pipeline : [FixedLengthFrameDecoder#0, LoggingHandler#0, DefaultChannelPipeline$TailContext#0]. Channel : [id: 0x4824e86f, L:/127.0.0.1:8080 - R:/127.0.0.1:64332].
00:10:24.650 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x4824e86f, L:/127.0.0.1:8080 - R:/127.0.0.1:64332] READ: 10B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 66 66 66 66 66 66 5f 5f 5f 5f                   |ffffff____      |
+--------+-------------------------------------------------+----------------+

固定分隔符

        发送方发送数据后在数据末尾添加固定标识,用以向接收方严明此位置为数据的结束位置,随后接收方根据特定的分隔符分割并接收数据。

        固定分隔符主要有以下两个类别:

  • LineBasedFrameDecoder:默认以'\n'或者'\r\n'作为分隔符。
    DelimiterBasedFrameDecoder :支持自定义分隔符。

        上述两种分隔符使用的时候均需要设置最大长度,达到最大长度后仍然没有出现分隔符,则抛出异常。

        服务端代码:

@Slf4j
public class HelloServer {public static void main(String[] args) {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>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024));socketChannel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));}});ChannelFuture channelFuture = serverBootstrap.bind(8080).sync();channelFuture.channel().closeFuture().sync();} catch (InterruptedException e) {log.error("Server error ", e);} finally {boss.shutdownGracefully();worker.shutdownGracefully();}}
}

        客户端代码:

public class HelloClient {static final Logger log = LoggerFactory.getLogger(HelloClient.class);public static void main(String[] args) {send();}private static void send() {NioEventLoopGroup worker = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(worker);bootstrap.channel(NioSocketChannel.class);bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){// channelActive会在连接channel建立成功后,会触发 active事件@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ByteBuf buffer = ctx.alloc().buffer();Random random = new Random();char ch = 'a';for (int i = 0; i < 10; i++) {for(int j = 0; j < random.nextInt(16) + 1; j++){buffer.writeByte(ch);}buffer.writeBytes("\n".toString().getBytes());ch++;}ctx.writeAndFlush(buffer);}});}});ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress("localhost", 8080));channelFuture.channel().closeFuture().sync();} catch (Exception e) {log.info("clinet error ", e);} finally {worker.shutdownGracefully();}}
}

        结果: 

#客户端结果00:18:56.518 [nioEventLoopGroup-2-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x13d89048, L:/127.0.0.1:61146 - R:localhost/127.0.0.1:8080] WRITE: 71B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 61 61 61 61 61 61 61 61 0a 62 62 62 62 62 62 62 |aaaaaaaa.bbbbbbb|
|00000010| 0a 63 63 63 63 63 0a 64 64 64 64 64 64 64 64 64 |.ccccc.ddddddddd|
|00000020| 64 0a 65 65 65 65 65 0a 66 66 0a 67 67 67 67 67 |d.eeeee.ff.ggggg|
|00000030| 0a 68 68 68 68 68 68 0a 69 69 69 69 69 69 69 0a |.hhhhhh.iiiiiii.|
|00000040| 6a 6a 6a 6a 6a 6a 0a                            |jjjjjj.         |
+--------+-------------------------------------------------+----------------+
00:18:56.518 [nioEventLoopGroup-2-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x13d89048, L:/127.0.0.1:61146 - R:localhost/127.0.0.1:8080] FLUSH#服务端结果00:18:56.534 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0xf0a94455, L:/127.0.0.1:8080 - R:/127.0.0.1:61146] READ: 8B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 61 61 61 61 61 61 61 61                         |aaaaaaaa        |
+--------+-------------------------------------------------+----------------+
00:18:56.534 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded inbound message PooledSlicedByteBuf(ridx: 0, widx: 8, cap: 8/8, unwrapped: PooledUnsafeDirectByteBuf(ridx: 9, widx: 71, cap: 1024)) that reached at the tail of the pipeline. Please check your pipeline configuration.
00:18:56.534 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded message pipeline : [LineBasedFrameDecoder#0, LoggingHandler#0, DefaultChannelPipeline$TailContext#0]. Channel : [id: 0xf0a94455, L:/127.0.0.1:8080 - R:/127.0.0.1:61146].
00:18:56.534 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0xf0a94455, L:/127.0.0.1:8080 - R:/127.0.0.1:61146] READ: 7B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 62 62 62 62 62 62 62                            |bbbbbbb         |
+--------+-------------------------------------------------+----------------+
00:18:56.534 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded inbound message PooledSlicedByteBuf(ridx: 0, widx: 7, cap: 7/7, unwrapped: PooledUnsafeDirectByteBuf(ridx: 17, widx: 71, cap: 1024)) that reached at the tail of the pipeline. Please check your pipeline configuration.
00:18:56.534 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded message pipeline : [LineBasedFrameDecoder#0, LoggingHandler#0, DefaultChannelPipeline$TailContext#0]. Channel : [id: 0xf0a94455, L:/127.0.0.1:8080 - R:/127.0.0.1:61146].
00:18:56.534 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0xf0a94455, L:/127.0.0.1:8080 - R:/127.0.0.1:61146] READ: 5B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 63 63 63 63 63                                  |ccccc           |
+--------+-------------------------------------------------+----------------+

预设长度 

        基于长度的帧解码器:

        使用时需要指定四个长度:

  • lengthFieldOffset:= 1 :偏移量(长度内容所在位置的距离开始处的偏移量的大小)
  • lengthFieldLength:= 2:代表的是标识长度的这个数据所占用的数据长度。
  • lengthAdjustment: = 1:长度内容到具体消息内容的偏移量。
  • initialBytesToStrip:= 3:需要剥离头信息的长度。(是不是需要剥离头,自定)一般我们是要头的。

        使用EmbededChannel编写演示代码

/*** 使用EmbededChannel测试LengthFieldDecoder*/
public class TestLengthFieldDecoder {public static void main(String[] args) {EmbeddedChannel channel = new EmbeddedChannel(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4),new LoggingHandler(LogLevel.INFO));ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();buildBuffer(buffer, "Hello, world");buildBuffer(buffer, "Hi, Hi");channel.writeInbound(buffer);}private static void buildBuffer(ByteBuf buffer, String str) {byte[] bytes = str.toString().getBytes();int length = bytes.length;buffer.writeInt(length);buffer.writeBytes(bytes);}
}

        结果

00:25:25.154 [main] INFO io.netty.handler.logging.LoggingHandler - [id: 0xembedded, L:embedded - R:embedded] READ: 12B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64             |Hello, world    |
+--------+-------------------------------------------------+----------------+
00:25:25.154 [main] INFO io.netty.handler.logging.LoggingHandler - [id: 0xembedded, L:embedded - R:embedded] READ: 6B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 69 2c 20 48 69                               |Hi, Hi          |
+--------+-------------------------------------------------+----------------+
00:25:25.154 [main] INFO io.netty.handler.logging.LoggingHandler - [id: 0xembedded, L:embedded - R:embedded] READ COMPLETE

常见协议代码举例

redis协议

        代码:

/*** set name zhangsan*  *3*  $3*  set*  $4*  name*  $8*  zhangsan*/
public class TestRedis {final static byte[] LINE = {13, 10};public static void main(String[] args) {NioEventLoopGroup worker = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(worker);bootstrap.channel(NioSocketChannel.class);bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ByteBuf buf = ctx.alloc().buffer();buf.writeBytes("auth 123456".getBytes()).writeBytes(LINE);ctx.writeAndFlush(buf);ByteBuf buffer = ctx.alloc().buffer();//                        super.channelInactive(ctx);buffer.writeBytes("*3".getBytes()).writeBytes(LINE);buffer.writeBytes("$3".getBytes()).writeBytes(LINE);buffer.writeBytes("set".getBytes()).writeBytes(LINE);buffer.writeBytes("$4".getBytes()).writeBytes(LINE);buffer.writeBytes("name".getBytes()).writeBytes(LINE);buffer.writeBytes("$8".getBytes()).writeBytes(LINE);buffer.writeBytes("zhangsan".getBytes()).writeBytes(LINE);ctx.writeAndFlush(buffer);}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buf = (ByteBuf) msg;System.out.println(buf.toString(Charset.defaultCharset()));}});}});ChannelFuture channelFuture = bootstrap.connect("localhost", 6379).sync();channelFuture.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();} finally {worker.shutdownGracefully();}}
}

        结果:

00:27:04.468 [nioEventLoopGroup-2-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x92af23ed, L:/127.0.0.1:62317 - R:localhost/127.0.0.1:6379] WRITE: 13B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 61 75 74 68 20 31 32 33 34 35 36 0d 0a          |auth 123456..   |
+--------+-------------------------------------------------+----------------+
00:27:04.469 [nioEventLoopGroup-2-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x92af23ed, L:/127.0.0.1:62317 - R:localhost/127.0.0.1:6379] FLUSH
00:27:04.469 [nioEventLoopGroup-2-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x92af23ed, L:/127.0.0.1:62317 - R:localhost/127.0.0.1:6379] WRITE: 37B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 2a 33 0d 0a 24 33 0d 0a 73 65 74 0d 0a 24 34 0d |*3..$3..set..$4.|
|00000010| 0a 6e 61 6d 65 0d 0a 24 38 0d 0a 7a 68 61 6e 67 |.name..$8..zhang|
|00000020| 73 61 6e 0d 0a                                  |san..           |
+--------+-------------------------------------------------+----------------+
00:27:04.469 [nioEventLoopGroup-2-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x92af23ed, L:/127.0.0.1:62317 - R:localhost/127.0.0.1:6379] FLUSH
00:27:04.470 [nioEventLoopGroup-2-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x92af23ed, L:/127.0.0.1:62317 - R:localhost/127.0.0.1:6379] READ: 10B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 2b 4f 4b 0d 0a 2b 4f 4b 0d 0a                   |+OK..+OK..      |
+--------+-------------------------------------------------+----------------+
+OK
+OK00:27:04.470 [nioEventLoopGroup-2-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x92af23ed, L:/127.0.0.1:62317 - R:localhost/127.0.0.1:6379] READ COMPLETE

http协议 

        代码:

@Slf4j
public class TestHttp {public static void main(String[] args) {NioEventLoopGroup boss = new NioEventLoopGroup();NioEventLoopGroup worker = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.channel(NioServerSocketChannel.class);bootstrap.group(boss, worker);bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));// Http编解码器ch.pipeline().addLast(new HttpServerCodec());// 入站处理器,可以只关心某一种类型的消息,根据消息的类型进行选择处理ch.pipeline().addLast(new SimpleChannelInboundHandler<HttpRequest>() {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) throws Exception {// 获取请求log.info(msg.uri());// 构建响应DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(msg.protocolVersion(), HttpResponseStatus.OK);byte[] bytes = "<h1>Hello, world</h1>".getBytes();httpResponse.headers().setInt(CONTENT_LENGTH, bytes.length);httpResponse.content().writeBytes(bytes);// 写回响应ctx.writeAndFlush(httpResponse);}});
/*                    ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {log.info("{}", msg.getClass());}});*/}});ChannelFuture channelFuture = bootstrap.bind(8080).sync();channelFuture.channel().closeFuture().sync();} catch (InterruptedException e) {
//            e.printStackTrace();log.error("server error : ", e);} finally {boss.shutdownGracefully();worker.shutdownGracefully();}}
}

        结果:

00:28:10.860 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x6b07a866, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:55348] READ: 1002B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 47 45 54 20 2f 68 65 6c 6c 6f 20 48 54 54 50 2f |GET /hello HTTP/|
|00000010| 31 2e 31 0d 0a 48 6f 73 74 3a 20 6c 6f 63 61 6c |1.1..Host: local|
|00000020| 68 6f 73 74 3a 38 30 38 30 0d 0a 43 6f 6e 6e 65 |host:8080..Conne|
|00000030| 63 74 69 6f 6e 3a 20 6b 65 65 70 2d 61 6c 69 76 |ction: keep-aliv|
|00000040| 65 0d 0a 73 65 63 2d 63 68 2d 75 61 3a 20 22 4d |e..sec-ch-ua: "M|
|00000050| 69 63 72 6f 73 6f 66 74 20 45 64 67 65 22 3b 76 |icrosoft Edge";v|
|00000060| 3d 22 31 32 35 22 2c 20 22 43 68 72 6f 6d 69 75 |="125", "Chromiu|
|00000070| 6d 22 3b 76 3d 22 31 32 35 22 2c 20 22 4e 6f 74 |m";v="125", "Not|
|00000080| 2e 41 2f 42 72 61 6e 64 22 3b 76 3d 22 32 34 22 |.A/Brand";v="24"|
|00000090| 0d 0a 73 65 63 2d 63 68 2d 75 61 2d 6d 6f 62 69 |..sec-ch-ua-mobi|
|000000a0| 6c 65 3a 20 3f 30 0d 0a 73 65 63 2d 63 68 2d 75 |le: ?0..sec-ch-u|
|000000b0| 61 2d 70 6c 61 74 66 6f 72 6d 3a 20 22 57 69 6e |a-platform: "Win|
|000000c0| 64 6f 77 73 22 0d 0a 55 70 67 72 61 64 65 2d 49 |dows"..Upgrade-I|
|000000d0| 6e 73 65 63 75 72 65 2d 52 65 71 75 65 73 74 73 |nsecure-Requests|
|000000e0| 3a 20 31 0d 0a 55 73 65 72 2d 41 67 65 6e 74 3a |: 1..User-Agent:|
|000000f0| 20 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 28 57 69 | Mozilla/5.0 (Wi|
|00000100| 6e 64 6f 77 73 20 4e 54 20 31 30 2e 30 3b 20 57 |ndows NT 10.0; W|
|00000110| 69 6e 36 34 3b 20 78 36 34 29 20 41 70 70 6c 65 |in64; x64) Apple|
|00000120| 57 65 62 4b 69 74 2f 35 33 37 2e 33 36 20 28 4b |WebKit/537.36 (K|
|00000130| 48 54 4d 4c 2c 20 6c 69 6b 65 20 47 65 63 6b 6f |HTML, like Gecko|
|00000140| 29 20 43 68 72 6f 6d 65 2f 31 32 35 2e 30 2e 30 |) Chrome/125.0.0|
|00000150| 2e 30 20 53 61 66 61 72 69 2f 35 33 37 2e 33 36 |.0 Safari/537.36|
|00000160| 20 45 64 67 2f 31 32 35 2e 30 2e 30 2e 30 0d 0a | Edg/125.0.0.0..|
|00000170| 41 63 63 65 70 74 3a 20 74 65 78 74 2f 68 74 6d |Accept: text/htm|
|00000180| 6c 2c 61 70 70 6c 69 63 61 74 69 6f 6e 2f 78 68 |l,application/xh|
|00000190| 74 6d 6c 2b 78 6d 6c 2c 61 70 70 6c 69 63 61 74 |tml+xml,applicat|
|000001a0| 69 6f 6e 2f 78 6d 6c 3b 71 3d 30 2e 39 2c 69 6d |ion/xml;q=0.9,im|
|000001b0| 61 67 65 2f 61 76 69 66 2c 69 6d 61 67 65 2f 77 |age/avif,image/w|
|000001c0| 65 62 70 2c 69 6d 61 67 65 2f 61 70 6e 67 2c 2a |ebp,image/apng,*|
|000001d0| 2f 2a 3b 71 3d 30 2e 38 2c 61 70 70 6c 69 63 61 |/*;q=0.8,applica|
|000001e0| 74 69 6f 6e 2f 73 69 67 6e 65 64 2d 65 78 63 68 |tion/signed-exch|
|000001f0| 61 6e 67 65 3b 76 3d 62 33 3b 71 3d 30 2e 37 0d |ange;v=b3;q=0.7.|
|00000200| 0a 53 65 63 2d 46 65 74 63 68 2d 53 69 74 65 3a |.Sec-Fetch-Site:|
|00000210| 20 6e 6f 6e 65 0d 0a 53 65 63 2d 46 65 74 63 68 | none..Sec-Fetch|
|00000220| 2d 4d 6f 64 65 3a 20 6e 61 76 69 67 61 74 65 0d |-Mode: navigate.|
|00000230| 0a 53 65 63 2d 46 65 74 63 68 2d 55 73 65 72 3a |.Sec-Fetch-User:|
|00000240| 20 3f 31 0d 0a 53 65 63 2d 46 65 74 63 68 2d 44 | ?1..Sec-Fetch-D|
|00000250| 65 73 74 3a 20 64 6f 63 75 6d 65 6e 74 0d 0a 41 |est: document..A|
|00000260| 63 63 65 70 74 2d 45 6e 63 6f 64 69 6e 67 3a 20 |ccept-Encoding: |
|00000270| 67 7a 69 70 2c 20 64 65 66 6c 61 74 65 2c 20 62 |gzip, deflate, b|
|00000280| 72 2c 20 7a 73 74 64 0d 0a 41 63 63 65 70 74 2d |r, zstd..Accept-|
|00000290| 4c 61 6e 67 75 61 67 65 3a 20 7a 68 2d 43 4e 2c |Language: zh-CN,|
|000002a0| 7a 68 3b 71 3d 30 2e 39 2c 65 6e 3b 71 3d 30 2e |zh;q=0.9,en;q=0.|
|000002b0| 38 2c 65 6e 2d 47 42 3b 71 3d 30 2e 37 2c 65 6e |8,en-GB;q=0.7,en|
|000002c0| 2d 55 53 3b 71 3d 30 2e 36 0d 0a 43 6f 6f 6b 69 |-US;q=0.6..Cooki|
|000002d0| 65 3a 20 49 64 65 61 2d 39 66 61 62 39 61 62 30 |e: Idea-9fab9ab0|
|000002e0| 3d 35 32 31 66 38 65 33 38 2d 62 34 32 35 2d 34 |=521f8e38-b425-4|
|000002f0| 63 62 36 2d 39 63 39 63 2d 32 61 65 64 31 66 38 |cb6-9c9c-2aed1f8|
|00000300| 64 32 66 38 30 3b 20 58 58 4c 5f 4a 4f 42 5f 4c |d2f80; XXL_JOB_L|
|00000310| 4f 47 49 4e 5f 49 44 45 4e 54 49 54 59 3d 37 62 |OGIN_IDENTITY=7b|
|00000320| 32 32 36 39 36 34 32 32 33 61 33 31 32 63 32 32 |226964223a312c22|
|00000330| 37 35 37 33 36 35 37 32 36 65 36 31 36 64 36 35 |757365726e616d65|
|00000340| 32 32 33 61 32 32 36 31 36 34 36 64 36 39 36 65 |223a2261646d696e|
|00000350| 32 32 32 63 32 32 37 30 36 31 37 33 37 33 37 37 |222c227061737377|
|00000360| 36 66 37 32 36 34 32 32 33 61 32 32 36 35 33 31 |6f7264223a226531|
|00000370| 33 30 36 31 36 34 36 33 33 33 33 39 33 34 33 39 |3061646333393439|
|00000380| 36 32 36 31 33 35 33 39 36 31 36 32 36 32 36 35 |6261353961626265|
|00000390| 33 35 33 36 36 35 33 30 33 35 33 37 36 36 33 32 |3536653035376632|
|000003a0| 33 30 36 36 33 38 33 38 33 33 36 35 32 32 32 63 |306638383365222c|
|000003b0| 32 32 37 32 36 66 36 63 36 35 32 32 33 61 33 31 |22726f6c65223a31|
|000003c0| 32 63 32 32 37 30 36 35 37 32 36 64 36 39 37 33 |2c227065726d6973|
|000003d0| 37 33 36 39 36 66 36 65 32 32 33 61 36 65 37 35 |73696f6e223a6e75|
|000003e0| 36 63 36 63 37 64 0d 0a 0d 0a                   |6c6c7d....      |
+--------+-------------------------------------------------+----------------+
00:28:10.871 [nioEventLoopGroup-3-1] INFO com.example.code.updatenetty.c6http.TestHttp - /hello
00:28:10.874 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x6b07a866, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:55348] WRITE: 60B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d |HTTP/1.1 200 OK.|
|00000010| 0a 63 6f 6e 74 65 6e 74 2d 6c 65 6e 67 74 68 3a |.content-length:|
|00000020| 20 32 31 0d 0a 0d 0a 3c 68 31 3e 48 65 6c 6c 6f | 21....<h1>Hello|
|00000030| 2c 20 77 6f 72 6c 64 3c 2f 68 31 3e             |, world</h1>    |
+--------+-------------------------------------------------+----------------+
00:28:10.875 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x6b07a866, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:55348] FLUSH
00:28:10.875 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded inbound message EmptyLastHttpContent that reached at the tail of the pipeline. Please check your pipeline configuration.
00:28:10.875 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded message pipeline : [LoggingHandler#0, HttpServerCodec#0, TestHttp$1$1#0, DefaultChannelPipeline$TailContext#0]. Channel : [id: 0x6b07a866, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:55348].
00:28:10.875 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x6b07a866, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:55348] READ COMPLETE
00:28:10.931 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x6b07a866, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:55348] READ: 928B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 47 45 54 20 2f 66 61 76 69 63 6f 6e 2e 69 63 6f |GET /favicon.ico|
|00000010| 20 48 54 54 50 2f 31 2e 31 0d 0a 48 6f 73 74 3a | HTTP/1.1..Host:|
|00000020| 20 6c 6f 63 61 6c 68 6f 73 74 3a 38 30 38 30 0d | localhost:8080.|
|00000030| 0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 6b 65 65 |.Connection: kee|
|00000040| 70 2d 61 6c 69 76 65 0d 0a 73 65 63 2d 63 68 2d |p-alive..sec-ch-|
|00000050| 75 61 3a 20 22 4d 69 63 72 6f 73 6f 66 74 20 45 |ua: "Microsoft E|
|00000060| 64 67 65 22 3b 76 3d 22 31 32 35 22 2c 20 22 43 |dge";v="125", "C|
|00000070| 68 72 6f 6d 69 75 6d 22 3b 76 3d 22 31 32 35 22 |hromium";v="125"|
|00000080| 2c 20 22 4e 6f 74 2e 41 2f 42 72 61 6e 64 22 3b |, "Not.A/Brand";|
|00000090| 76 3d 22 32 34 22 0d 0a 73 65 63 2d 63 68 2d 75 |v="24"..sec-ch-u|
|000000a0| 61 2d 6d 6f 62 69 6c 65 3a 20 3f 30 0d 0a 55 73 |a-mobile: ?0..Us|
|000000b0| 65 72 2d 41 67 65 6e 74 3a 20 4d 6f 7a 69 6c 6c |er-Agent: Mozill|
|000000c0| 61 2f 35 2e 30 20 28 57 69 6e 64 6f 77 73 20 4e |a/5.0 (Windows N|
|000000d0| 54 20 31 30 2e 30 3b 20 57 69 6e 36 34 3b 20 78 |T 10.0; Win64; x|
|000000e0| 36 34 29 20 41 70 70 6c 65 57 65 62 4b 69 74 2f |64) AppleWebKit/|
|000000f0| 35 33 37 2e 33 36 20 28 4b 48 54 4d 4c 2c 20 6c |537.36 (KHTML, l|
|00000100| 69 6b 65 20 47 65 63 6b 6f 29 20 43 68 72 6f 6d |ike Gecko) Chrom|
|00000110| 65 2f 31 32 35 2e 30 2e 30 2e 30 20 53 61 66 61 |e/125.0.0.0 Safa|
|00000120| 72 69 2f 35 33 37 2e 33 36 20 45 64 67 2f 31 32 |ri/537.36 Edg/12|
|00000130| 35 2e 30 2e 30 2e 30 0d 0a 73 65 63 2d 63 68 2d |5.0.0.0..sec-ch-|
|00000140| 75 61 2d 70 6c 61 74 66 6f 72 6d 3a 20 22 57 69 |ua-platform: "Wi|
|00000150| 6e 64 6f 77 73 22 0d 0a 41 63 63 65 70 74 3a 20 |ndows"..Accept: |
|00000160| 69 6d 61 67 65 2f 61 76 69 66 2c 69 6d 61 67 65 |image/avif,image|
|00000170| 2f 77 65 62 70 2c 69 6d 61 67 65 2f 61 70 6e 67 |/webp,image/apng|
|00000180| 2c 69 6d 61 67 65 2f 73 76 67 2b 78 6d 6c 2c 69 |,image/svg+xml,i|
|00000190| 6d 61 67 65 2f 2a 2c 2a 2f 2a 3b 71 3d 30 2e 38 |mage/*,*/*;q=0.8|
|000001a0| 0d 0a 53 65 63 2d 46 65 74 63 68 2d 53 69 74 65 |..Sec-Fetch-Site|
|000001b0| 3a 20 73 61 6d 65 2d 6f 72 69 67 69 6e 0d 0a 53 |: same-origin..S|
|000001c0| 65 63 2d 46 65 74 63 68 2d 4d 6f 64 65 3a 20 6e |ec-Fetch-Mode: n|
|000001d0| 6f 2d 63 6f 72 73 0d 0a 53 65 63 2d 46 65 74 63 |o-cors..Sec-Fetc|
|000001e0| 68 2d 44 65 73 74 3a 20 69 6d 61 67 65 0d 0a 52 |h-Dest: image..R|
|000001f0| 65 66 65 72 65 72 3a 20 68 74 74 70 3a 2f 2f 6c |eferer: http://l|
|00000200| 6f 63 61 6c 68 6f 73 74 3a 38 30 38 30 2f 68 65 |ocalhost:8080/he|
|00000210| 6c 6c 6f 0d 0a 41 63 63 65 70 74 2d 45 6e 63 6f |llo..Accept-Enco|
|00000220| 64 69 6e 67 3a 20 67 7a 69 70 2c 20 64 65 66 6c |ding: gzip, defl|
|00000230| 61 74 65 2c 20 62 72 2c 20 7a 73 74 64 0d 0a 41 |ate, br, zstd..A|
|00000240| 63 63 65 70 74 2d 4c 61 6e 67 75 61 67 65 3a 20 |ccept-Language: |
|00000250| 7a 68 2d 43 4e 2c 7a 68 3b 71 3d 30 2e 39 2c 65 |zh-CN,zh;q=0.9,e|
|00000260| 6e 3b 71 3d 30 2e 38 2c 65 6e 2d 47 42 3b 71 3d |n;q=0.8,en-GB;q=|
|00000270| 30 2e 37 2c 65 6e 2d 55 53 3b 71 3d 30 2e 36 0d |0.7,en-US;q=0.6.|
|00000280| 0a 43 6f 6f 6b 69 65 3a 20 49 64 65 61 2d 39 66 |.Cookie: Idea-9f|
|00000290| 61 62 39 61 62 30 3d 35 32 31 66 38 65 33 38 2d |ab9ab0=521f8e38-|
|000002a0| 62 34 32 35 2d 34 63 62 36 2d 39 63 39 63 2d 32 |b425-4cb6-9c9c-2|
|000002b0| 61 65 64 31 66 38 64 32 66 38 30 3b 20 58 58 4c |aed1f8d2f80; XXL|
|000002c0| 5f 4a 4f 42 5f 4c 4f 47 49 4e 5f 49 44 45 4e 54 |_JOB_LOGIN_IDENT|
|000002d0| 49 54 59 3d 37 62 32 32 36 39 36 34 32 32 33 61 |ITY=7b226964223a|
|000002e0| 33 31 32 63 32 32 37 35 37 33 36 35 37 32 36 65 |312c22757365726e|
|000002f0| 36 31 36 64 36 35 32 32 33 61 32 32 36 31 36 34 |616d65223a226164|
|00000300| 36 64 36 39 36 65 32 32 32 63 32 32 37 30 36 31 |6d696e222c227061|
|00000310| 37 33 37 33 37 37 36 66 37 32 36 34 32 32 33 61 |7373776f7264223a|
|00000320| 32 32 36 35 33 31 33 30 36 31 36 34 36 33 33 33 |2265313061646333|
|00000330| 33 39 33 34 33 39 36 32 36 31 33 35 33 39 36 31 |3934396261353961|
|00000340| 36 32 36 32 36 35 33 35 33 36 36 35 33 30 33 35 |6262653536653035|
|00000350| 33 37 36 36 33 32 33 30 36 36 33 38 33 38 33 33 |3766323066383833|
|00000360| 36 35 32 32 32 63 32 32 37 32 36 66 36 63 36 35 |65222c22726f6c65|
|00000370| 32 32 33 61 33 31 32 63 32 32 37 30 36 35 37 32 |223a312c22706572|
|00000380| 36 64 36 39 37 33 37 33 36 39 36 66 36 65 32 32 |6d697373696f6e22|
|00000390| 33 61 36 65 37 35 36 63 36 63 37 64 0d 0a 0d 0a |3a6e756c6c7d....|
+--------+-------------------------------------------------+----------------+
00:28:10.931 [nioEventLoopGroup-3-1] INFO com.example.code.updatenetty.c6http.TestHttp - /favicon.ico
00:28:10.931 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x6b07a866, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:55348] WRITE: 60B+-------------------------------------------------+|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 54 54 50 2f 31 2e 31 20 32 30 30 20 4f 4b 0d |HTTP/1.1 200 OK.|
|00000010| 0a 63 6f 6e 74 65 6e 74 2d 6c 65 6e 67 74 68 3a |.content-length:|
|00000020| 20 32 31 0d 0a 0d 0a 3c 68 31 3e 48 65 6c 6c 6f | 21....<h1>Hello|
|00000030| 2c 20 77 6f 72 6c 64 3c 2f 68 31 3e             |, world</h1>    |
+--------+-------------------------------------------------+----------------+
00:28:10.932 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x6b07a866, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:55348] FLUSH
00:28:10.932 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded inbound message EmptyLastHttpContent that reached at the tail of the pipeline. Please check your pipeline configuration.
00:28:10.932 [nioEventLoopGroup-3-1] DEBUG io.netty.channel.DefaultChannelPipeline - Discarded message pipeline : [LoggingHandler#0, HttpServerCodec#0, TestHttp$1$1#0, DefaultChannelPipeline$TailContext#0]. Channel : [id: 0x6b07a866, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:55348].
00:28:10.932 [nioEventLoopGroup-3-1] INFO io.netty.handler.logging.LoggingHandler - [id: 0x6b07a866, L:/0:0:0:0:0:0:0:1:8080 - R:/0:0:0:0:0:0:0:1:55348] READ COMPLETE

 参考链接

Netty使用篇:半包&粘包_netty 半包粘包-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/19740.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R语言绘图 | 双Y轴截断图

教程原文&#xff1a;双Y轴截断图绘制教程 本期教程 本期教程&#xff0c;我们提供的原文的译文&#xff0c;若有需求请回复关键词&#xff1a;20240529 小杜的生信笔记&#xff0c;自2021年11月开始做的知识分享&#xff0c;主要内容是R语言绘图教程、转录组上游分析、转录组…

HarmonyOS鸿蒙学习笔记(27)resources目录说明

resources目录说明 目录结构目录说明base目录rawfile目录resfile目录资源组目录 参考资料 目录结构 在HarmonyOS的项目结构中&#xff0c;有resources目录&#xff0c;用于存放应用/服务所用到的资源文件&#xff0c;如图形、多媒体、字符串、布局文件等。关于资源文件&#x…

基于Linux的文件操作(socket操作)

基于Linux的文件操作&#xff08;socket操作&#xff09; 1. 文件描述符基本概念文件描述符的定义&#xff1a;标准文件描述符&#xff1a;文件描述符的分配&#xff1a; 2. 文件描述符操作打开文件读取文件中的数据 在linux中&#xff0c;socket也被认为是文件的一种&#xff…

redis 高可用及哨兵模式 @by_TWJ

目录 1. 高可用2. redis 哨兵模式3. 图文的方式让我们读懂这几个算法3.1. Raft算法 - 图文3.2. Paxos算法 - 图文3.3. 区别&#xff1a; 1. 高可用 在 Redis 中&#xff0c;实现 高可用 的技术主要包括 持久化、复制、哨兵 和 集群&#xff0c;下面简单说明它们的作用&#xf…

jpom ruoyi 发布后端

添加ssh 添加标签 添加仓库 添加构建 构建 命令 APP_NAMEenterprise IMAGE_NAMEenterprise:latest APP_PORT8080 RUN_ENVjenkins cd ruoyi-admin docker stop $APP_NAME || true docker rm $APP_NAME || true docker rmi $IMAGE_NAME || true docker build -f Dockerfil…

排序算法(一) 基础排序算法

排序算法 基础排序算法 排序本质&#xff1a;减小逆序对的过程 在基础排序算法中&#xff0c;将待排序序列分为相对有序区与相对无序区。 每次遍历到数组末尾称为一轮。 冒泡排序(无序区-有序区, O ( n 2 ) O(n^2) O(n2),稳定,就地) 在每一轮中&#xff0c;逐次与下一邻项…

DNF手游攻略:勇士进阶指南!

在即将到来的6月5日&#xff0c;《DNF手游》将迎来一场盛大的更新&#xff0c;此次更新带来了大量新内容和玩法&#xff0c;极大丰富了游戏的体验。本文将为广大玩家详细解析此次更新的亮点&#xff0c;包括新增的组队挑战玩法“罗特斯入门团本”、新星使宠物的推出、宠物进化功…

Sectigo EV代码签名证书费用是多少?

随着数字化时代的到来&#xff0c;软件开发者和企业面临着日益严峻的安全挑战。为了确保他们的软件产品免受恶意篡改和仿冒的威胁&#xff0c;代码签名证书应运而生&#xff0c;成为了业界广泛认可的安全解决方案。在众多代码签名证书提供商中&#xff0c;Sectigo以其卓越的信誉…

整理GTX收发器示例工程(高速收发器十一)

前文分析了xilinx官方提供的GTX IP示例工程&#xff0c;该代码的结构比较混乱&#xff0c;本文将该代码进行梳理&#xff0c;形成一个便于使用的模块&#xff0c;后续如果要使用多通道的收发器&#xff0c;多次例化某个模块就行了。 下图是官方例程中GTX IP相关模块的RTL视图&a…

停车场车位引导系统方案升级实施步骤流程是什么,有什么注意事项

停车场车位引导系统是一种现代化的停车管理系统&#xff0c;它通过实时监测车位占用情况&#xff0c;并向驾驶员提供准确的空闲车位导航信息&#xff0c;从而提高停车场的使用效率和用户体验。随着城市交通的快速发展和车辆数量的不断增加&#xff0c;停车场车位引导系统已成为…

薄膜沉积的均匀性怎么计算?

知识星球&#xff08;星球名&#xff1a;芯片制造与封测技术社区&#xff0c;星球号&#xff1a;63559049&#xff09;里的学员问&#xff1a;经常听带我的工程师说膜层的均匀性不好&#xff0c;均匀性是怎么计算的? 什么是薄膜沉积的均匀性&#xff1f;薄膜均匀性指的是薄膜…

Leetcode刷题笔记7

69. x 的平方根 69. x 的平方根 - 力扣&#xff08;LeetCode&#xff09; 假设求17的平方根 解法一&#xff1a;暴力解法 从1开始依次尝试 比如1的平方是1&#xff0c;2的平方是4...直到5的平方&#xff0c;25>17&#xff0c;所以一定是4点几的平方&#xff0c;所以等于4…

WSL2-Ubuntu22.04-配置

WSL2-Ubuntu22.04-配置 准备1. WSL相关命令[^1]2. WSL2-Ubuntu22.04可视化3. WSL2 设置 CUDA4. 设置OpenGL 本文介绍了WSL2的基本使用方法及可视化&#xff0c;着重介绍了GPU和OpenGL的设置。 准备 名称版本windows11wsl2CUDA12.5 1. WSL相关命令1 查看已安装的wsl distribut…

官方小游戏项目

一 项目原理&#xff1a;看广告&#xff0c;操作简单&#xff0c;时间自由&#xff0c;适合利用业余时间来做&#xff0c;一个广告大概在15s-30s之间。 二 介绍&#xff1a;给你开代理权限&#xff0c;你就有独立后台管理系统&#xff0c;监测每台手机每条广告的情况&#xff0…

MySQL数据表的“增删查改“

我们学习数据库, 最重要的就是要学会对数据表表进行"增删查改"(CRUD).(C -- create, R -- retrieve, U -- update, D -- delete) 目录 一. "增"(create) 1. 普通新增 2. 指定列新增 3. 一次插入多行 4. 用insert插入时间 5. 小结 二. "查"…

AI科技,赋能企业财务管理

AI技术已深入千行百业&#xff0c;其实际任务解决能力愈发凸显和强劲。正如乔布斯所强调“技术不是为工程师而生&#xff0c;而是为应用而生”。 胜意科技深度集成业内领先技术&#xff0c;将AI融入到实际的财务工作流中&#xff0c;与OCR、RPA等智能技术组合式输出&#xff0c…

Qt-qrencode生成二维码

Qt-qrencode开发-生成二维码&#x1f4c0; 文章目录 Qt-qrencode开发-生成二维码&#x1f4c0;[toc]1、概述&#x1f4f8;2、实现效果&#x1f4bd;3、编译qrencode&#x1f50d;4、在QT中引入编译为静态库的QRencode5、在Qt中直接使用QRencode源码6、在Qt中使用QRencode生成二…

Django Celery技术详解

文章目录 简介安装和配置创建并调度任务启动Celery Worker在视图中调用异步任务拓展功能 简介 Django Celery 是一个为Django应用程序提供异步任务处理能力的强大工具。它通过与消息代理&#xff08;如RabbitMQ、Redis&#xff09;集成&#xff0c;可以轻松地处理需要长时间运…

LAMP分布式安全方案搭建网页 (LinuxCentOS7+Apache+Mariadb+PHP)包括服务端口及防火墙规则配置

目录 一、实验目的 二、设计方案及规划 三、实验内容及步骤 &#xff08;1&#xff09;实验前基础配置 &#xff08;2&#xff09;Test配置&#xff0c;安装Firefox浏览器和图形界面 &#xff08;3&#xff09;Web安装Apache &#xff08;4&#xff09;Database安装Mari…

微服务架构-微服务架构的挑战与微服务化的具体时机

目录 一、微服务架构的挑战 1.1 概述 1.2 服务拆分 1.3 开发挑战 1.4 测试挑战 1.4.1 开箱即用、一键部署的集成环境 1.4.2 测试场景和测试确定性 1.4.3 微服务相关的非功能测试 1.4.4 自动化测试 1.5 运维挑战 1.5.1 监控 1.5.2 部署 1.5.3 问题追查 1.5.4 依赖管…