- 浏览: 787294 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
萨琳娜啊:
Java读源码之Netty深入剖析网盘地址:https://p ...
Netty源码学习-FileRegion -
飞天奔月:
写得有趣 ^_^
那一年你定义了一个接口 -
GoldRoger:
第二个方法很好
java-判断一个自然数是否是某个数的平方。当然不能使用开方运算 -
bylijinnan:
<script>alert("close ...
自己动手实现Java Validation -
paul920531:
39行有个bug:"int j=new Random ...
java-蓄水池抽样-要求从N个元素中随机的抽取k个元素,其中N无法确定
先看看LengthFieldBasedFrameDecoder的官方API
http://docs.jboss.org/netty/3.1/api/org/jboss/netty/handler/codec/frame/LengthFieldBasedFrameDecoder.html
API举例说明了LengthFieldBasedFrameDecoder的解析机制,如下:
实际消息内容是“HELLO, WORLD”,长度是12 bytes(注意逗号后面有一个空格)
实例1
lengthFieldLength = 2表示“Length”的长度,而“Length”的值
就是“Actual Content”的长度(0x000C, 也就是12):
实例2
initialBytesToStrip = 2 表示在decode时,要去掉多少个字节
在这个例子,表示要去掉“Length”(2个字节)
可以看到,AFTER DECODE后,“Length”没有了,只剩下“Actual Content”:
实例3
与实例1不同,这里“Length”的值不是“Actual Content”的长度,而是
整个消息的长度(0x000E,14 = 2 + 12)。用lengthAdjustment=-2来表示
“Actual Content”的长度要减2:
wholeLength = valueOf(Length) = 14
actualContentLength = wholeLength + lengthAdjustment = 14 + (-2)=12
实例4
这个例子多了一个“Header 1”(oxCAFE,长度为2 )
用 lengthFieldOffset = 2表示“Length”从第3个字节开始
“Length”的值仍然是“Actual Content ”的长度,不过“Length”自身的
长度是3 (值是0x00000C,而不是上面的0x000C)
实例5
与实例4不同的地方是,“Length”和“Header 1”的位置调换了
wholeLength = valueOf(Length) = 14
actualContentLength = wholeLength + lengthAdjustment = 14 + 2=16
因此在decode时,会认为“Header 1”也是“Actual Content”的一部分
实例6
看起来要比之前的例子复杂一些,但其实是上面例子的组合
lengthFieldOffset = 1表示“Length”从第2个字节开始
lengthFieldLength = 2表示“Length”的长度是2
lengthAdjustment = 1表示“HDR2”的长度是1:
wholeLength = valueOf(Length) = 0x000C = 12
actualContentLength = wholeLength + lengthAdjustment = 12 + 1=13
decode时,会认为“Length”后面的13个字节都是“Actual Content”,
因此会认为“HDR2”也是“Actual Content”的一部分
initialBytesToStrip = 3 表示decode时,去掉3个字节
实例7
与实例6不同的是,lengthAdjustment = -3,是负数
因此,
wholeLength = valueOf(Length) = 0x0010 = 16
actualContentLength = wholeLength + lengthAdjustment = 16 + (-3)=13
decode时,会认为“Length”后面的13个字节都是“Actual Content”,
最终效果与实例6一样
API看完,我们来看看源码(只保留关键代码):
http://docs.jboss.org/netty/3.1/api/org/jboss/netty/handler/codec/frame/LengthFieldBasedFrameDecoder.html
API举例说明了LengthFieldBasedFrameDecoder的解析机制,如下:
实际消息内容是“HELLO, WORLD”,长度是12 bytes(注意逗号后面有一个空格)
实例1
lengthFieldLength = 2表示“Length”的长度,而“Length”的值
就是“Actual Content”的长度(0x000C, 也就是12):
lengthFieldOffset = 0 lengthFieldLength = 2 lengthAdjustment = 0 initialBytesToStrip = 0 (= do not strip header) BEFORE DECODE (14 bytes) AFTER DECODE (14 bytes) +--------+----------------+ +--------+----------------+ | Length | Actual Content |----->| Length | Actual Content | | 0x000C | "HELLO, WORLD" | | 0x000C | "HELLO, WORLD" | +--------+----------------+ +--------+----------------+
实例2
initialBytesToStrip = 2 表示在decode时,要去掉多少个字节
在这个例子,表示要去掉“Length”(2个字节)
可以看到,AFTER DECODE后,“Length”没有了,只剩下“Actual Content”:
lengthFieldOffset = 0 lengthFieldLength = 2 lengthAdjustment = 0 initialBytesToStrip = 2 (= the length of the Length field) BEFORE DECODE (14 bytes) AFTER DECODE (12 bytes) +--------+----------------+ +----------------+ | Length | Actual Content |----->| Actual Content | | 0x000C | "HELLO, WORLD" | | "HELLO, WORLD" | +--------+----------------+ +----------------+
实例3
与实例1不同,这里“Length”的值不是“Actual Content”的长度,而是
整个消息的长度(0x000E,14 = 2 + 12)。用lengthAdjustment=-2来表示
“Actual Content”的长度要减2:
wholeLength = valueOf(Length) = 14
actualContentLength = wholeLength + lengthAdjustment = 14 + (-2)=12
lengthFieldOffset = 0 lengthFieldLength = 2 lengthAdjustment = -2 (= the length of the Length field) initialBytesToStrip = 0 BEFORE DECODE (14 bytes) AFTER DECODE (14 bytes) +--------+----------------+ +--------+----------------+ | Length | Actual Content |----->| Length | Actual Content | | 0x000E | "HELLO, WORLD" | | 0x000E | "HELLO, WORLD" | +--------+----------------+ +--------+----------------+
实例4
这个例子多了一个“Header 1”(oxCAFE,长度为2 )
用 lengthFieldOffset = 2表示“Length”从第3个字节开始
“Length”的值仍然是“Actual Content ”的长度,不过“Length”自身的
长度是3 (值是0x00000C,而不是上面的0x000C)
lengthFieldOffset = 2 (= the length of Header 1) lengthFieldLength = 3 lengthAdjustment = 0 initialBytesToStrip = 0 BEFORE DECODE (17 bytes) AFTER DECODE (17 bytes) +----------+----------+----------------+ +----------+----------+----------------+ | Header 1 | Length | Actual Content |----->| Header 1 | Length | Actual Content | | 0xCAFE | 0x00000C | "HELLO, WORLD" | | 0xCAFE | 0x00000C | "HELLO, WORLD" | +----------+----------+----------------+ +----------+----------+----------------+
实例5
与实例4不同的地方是,“Length”和“Header 1”的位置调换了
wholeLength = valueOf(Length) = 14
actualContentLength = wholeLength + lengthAdjustment = 14 + 2=16
因此在decode时,会认为“Header 1”也是“Actual Content”的一部分
lengthFieldOffset = 0 lengthFieldLength = 3 lengthAdjustment = 2 (= the length of Header 1) initialBytesToStrip = 0 BEFORE DECODE (17 bytes) AFTER DECODE (17 bytes) +----------+----------+----------------+ +----------+----------+----------------+ | Length | Header 1 | Actual Content |----->| Length | Header 1 | Actual Content | | 0x00000C | 0xCAFE | "HELLO, WORLD" | | 0x00000C | 0xCAFE | "HELLO, WORLD" | +----------+----------+----------------+ +----------+----------+----------------+
实例6
看起来要比之前的例子复杂一些,但其实是上面例子的组合
lengthFieldOffset = 1表示“Length”从第2个字节开始
lengthFieldLength = 2表示“Length”的长度是2
lengthAdjustment = 1表示“HDR2”的长度是1:
wholeLength = valueOf(Length) = 0x000C = 12
actualContentLength = wholeLength + lengthAdjustment = 12 + 1=13
decode时,会认为“Length”后面的13个字节都是“Actual Content”,
因此会认为“HDR2”也是“Actual Content”的一部分
initialBytesToStrip = 3 表示decode时,去掉3个字节
lengthFieldOffset = 1 (= the length of HDR1) lengthFieldLength = 2 lengthAdjustment = 1 (= the length of HDR2) initialBytesToStrip = 3 (= the length of HDR1 + LEN) BEFORE DECODE (16 bytes) AFTER DECODE (13 bytes) +------+--------+------+----------------+ +------+----------------+ | HDR1 | Length | HDR2 | Actual Content |----->| HDR2 | Actual Content | | 0xCA | 0x000C | 0xFE | "HELLO, WORLD" | | 0xFE | "HELLO, WORLD" | +------+--------+------+----------------+ +------+----------------+
实例7
与实例6不同的是,lengthAdjustment = -3,是负数
因此,
wholeLength = valueOf(Length) = 0x0010 = 16
actualContentLength = wholeLength + lengthAdjustment = 16 + (-3)=13
decode时,会认为“Length”后面的13个字节都是“Actual Content”,
最终效果与实例6一样
lengthFieldOffset = 1 lengthFieldLength = 2 lengthAdjustment = -3 (= the length of HDR1 + LEN, negative) initialBytesToStrip = 3 BEFORE DECODE (16 bytes) AFTER DECODE (13 bytes) +------+--------+------+----------------+ +------+----------------+ | HDR1 | Length | HDR2 | Actual Content |----->| HDR2 | Actual Content | | 0xCA | 0x0010 | 0xFE | "HELLO, WORLD" | | 0xFE | "HELLO, WORLD" | +------+--------+------+----------------+ +------+----------------+
API看完,我们来看看源码(只保留关键代码):
public class LengthFieldBasedFrameDecoder extends FrameDecoder { private final int maxFrameLength; //超出此长度的Frame将被丢弃 private final int lengthFieldOffset; private final int lengthFieldLength; private final int lengthFieldEndOffset; //这个值等于lengthFieldOffset + lengthFieldLength private final int lengthAdjustment; private final int initialBytesToStrip; protected Object decode( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { //数据未完整,先不处理 if (buffer.readableBytes() < lengthFieldEndOffset) { return null; } /* 先读取“Length”的值 在LengthFieldBasedFrameDecoder的构造函数中,限定了“Length”的长度: “lengthFieldLength must be either 1, 2, 3, 4, or 8” 单位是bytes。这个限定不知从何而来,先不管 由于接收到的数据的类型是ChannelBuffer,也就是byte[],那么在读取时, 就应该根据长度来分割数据 例如,lengthFieldLength=3,说明读取前3个字节就得到“Length”的值 读取时,用到了位操作,ByteOrder是BIG_ENDIAN,因此高位在前,要左移位: public int getUnsignedMedium(int index) { return (array[index] & 0xff) << 16 | (array[index + 1] & 0xff) << 8 | (array[index + 2] & 0xff) << 0; } 注意到,这个方法不会改变readerIndex 下面代码的frameLength,其实就是上面API分析时提到的valueOf(Length) */ int actualLengthFieldOffset = buffer.readerIndex() + lengthFieldOffset; long frameLength; switch (lengthFieldLength) { case 1: frameLength = buffer.getUnsignedByte(actualLengthFieldOffset); break; case 2: frameLength = buffer.getUnsignedShort(actualLengthFieldOffset); break; case 3: frameLength = buffer.getUnsignedMedium(actualLengthFieldOffset); break; case 4: frameLength = buffer.getUnsignedInt(actualLengthFieldOffset); break; case 8: frameLength = buffer.getLong(actualLengthFieldOffset); break; default: throw new Error("should not reach here"); } //如分析API时所说,要加上lengthAdjustment //那为什么 还要加上lengthFieldEndOffset? //加上之后,frameLength就代表整个frame的长度了,包括前缀和“Actual Content” frameLength += lengthAdjustment + lengthFieldEndOffset; int frameLengthInt = (int) frameLength; //数据未完整,先不处理 if (buffer.readableBytes() < frameLengthInt) { return null; } //readerIndex往后移,跳过指定的字节,不读取 buffer.skipBytes(initialBytesToStrip); // extract frame ,读取消息的内容 int readerIndex = buffer.readerIndex(); int actualFrameLength = frameLengthInt - initialBytesToStrip; ChannelBuffer frame = extractFrame(buffer, readerIndex, actualFrameLength); //extractFrame方法不改变buffer的readerIndex,因此要手动设置 buffer.readerIndex(readerIndex + actualFrameLength); return frame; } //这个方法创建了新的ChannelBuffer,不影响原buffer protected ChannelBuffer extractFrame(ChannelBuffer buffer, int index, int length) { ChannelBuffer frame = buffer.factory().getBuffer(length); frame.writeBytes(buffer, index, length); return frame; } }
发表评论
-
TCP的TIME-WAIT
2014-04-23 16:35 1198原文连接:http://vincent.bernat.im/e ... -
《TCPIP详解卷1》学习-拥塞避免
2014-01-15 15:16 159拥塞避免算法、 ... -
Netty源码学习-HTTP-tunnel
2014-01-14 18:19 4304Netty关于HTTP tunnel的说明: http://d ... -
Netty源码学习-FileRegion
2013-12-31 17:17 5661今天看org.jboss.netty.example.http ... -
Netty源码学习-HttpChunkAggregator-HttpRequestEncoder-HttpResponseDecoder
2013-12-27 16:10 4090今天看Netty如何实现一个Http Server org.j ... -
Netty源码学习-ReadTimeoutHandler
2013-12-26 17:53 3838ReadTimeoutHandler的实现思 ... -
Netty学习笔记
2013-12-25 18:39 1488本文是阅读以下两篇文章时: http://seeallhear ... -
Netty源码学习-ChannelHandler
2013-12-25 18:12 1636一般来说,“有状态”的ChannelHandler不应 ... -
Netty源码学习-ServerBootstrap启动及事件处理过程
2013-12-19 20:11 10764Netty是采用了Reactor模式的多线程版本,建议先看下面 ... -
Netty源码学习-Java-NIO-Reactor
2013-12-19 18:21 4895Netty里面采用了NIO-based Reactor Pat ... -
Netty源码学习-ReplayingDecoder
2013-12-13 20:21 4267ReplayingDecoder是FrameDecoder的子 ... -
Netty源码学习-DefaultChannelPipeline2
2013-12-11 15:47 1285Netty3的API http://docs.jboss.or ... -
Netty源码学习-CompositeChannelBuffer
2013-12-06 15:54 2762CompositeChannelBuffer体现了Netty的 ... -
Netty源码学习-DelimiterBasedFrameDecoder
2013-12-05 18:36 9562看DelimiterBasedFrameDecoder的AP ... -
Netty源码学习-ObjectEncoder和ObjectDecoder
2013-12-05 16:06 5007Netty中传递对象的思路很直观: Netty中数据的传递是基 ... -
Netty源码学习-FrameDecoder
2013-11-28 18:38 3939Netty 3.x的user guide里FrameDecod ... -
Netty源码学习-DefaultChannelPipeline
2013-11-27 17:00 2243package com.ljn.channel; /** ...
相关推荐
在本节"Netty源码教程-3"中,我们将深入探讨Netty这一高性能、异步事件驱动的网络应用程序框架。Netty广泛应用于各种分布式系统、服务器和客户端应用,尤其在处理高并发、低延迟的网络通信场景下,其优势尤为突出。...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的...通过研读Netty源码,不仅可以提升对网络编程的理解,还能掌握一种高性能的框架设计思想,对于提升个人技术水平和解决实际问题大有裨益。
Netty 是一个高性能、异步事件驱动...通过对Netty源码的学习,开发者不仅可以掌握网络编程的最佳实践,还能深入了解Java并发编程、内存管理以及性能优化等核心技能,对提升个人技术水平和解决实际问题具有极大的帮助。
“mini-netty-master”项目的源码可能会涵盖上述的一些或全部知识点,通过学习和分析这个简化版的实现,你可以更好地理解Netty的设计思想和使用方式,进阶到源码阅读将有助于深入理解Netty的内部工作原理。...
通过学习这本书的源码仓库,我们可以深入了解Netty的设计理念和最佳实践。 Netty的核心特性包括: 1. **异步事件驱动**:Netty基于Java NIO(非阻塞I/O)构建,实现了异步事件驱动的网络通信模型。这使得Netty能够...
Netty 是一个高性能、异步事件驱动的...总之,Netty 源码是一个很好的学习平台,可以深入了解网络编程、并发处理以及高效 I/O 设计。通过分析源码,不仅可以提升自己的技术能力,还能为解决实际问题提供灵感和参考。
总之,《RGP-NETTY:死磕NETTY原始码-NETTY原始码深度解析》是一个深入探索Netty源码的旅程,它将带你走进Netty的内核世界,让你对网络编程有更深的认识和掌握。对于任何希望提升Java网络编程能力的开发者来说,这都...
4. **强大的编码和解码器**:Netty 提供了丰富的编解码器,如LengthFieldBasedFrameDecoder用于处理带有长度字段的协议,LineBasedFrameDecoder用于按行解析数据等,这些组件使得处理各种网络协议变得非常便捷。...
Java Nety是一个高性能、异步事件...对于Java开发者来说,深入学习Netty源码不仅可以提升网络编程技能,也有助于解决实际问题,比如优化性能、处理异常、实现自定义协议等。因此,Netty源码是Java学习者宝贵的资源。
- 探索编解码器:Netty提供了各种预定义的编解码器,如LineBasedFrameDecoder、LengthFieldBasedFrameDecoder等,用于将原始的字节流转换为有意义的对象。 在实际项目中,你可以用Netty5来构建高性能的网络服务,...
总的来说,通过研究 Netty 的源码,开发者不仅可以掌握网络编程的最佳实践,还能学习到许多 Java 高级特性和设计模式的应用,从而提升自身的编程技能。无论是开发高性能的网络应用,还是进行系统优化,Netty 源码都...
以上仅是Netty源码分析的一些关键点,实际的学习中还需要结合具体代码和实际案例来深入理解。在分析源码的过程中,我们通常会关注类的设计模式、线程模型、内存管理以及性能优化等方面,这对于提升网络编程和系统...
"Netty-in-Action-Master" 的源码可能涵盖了这些知识点的实践应用,通过学习这些源码,开发者能更深入地理解 Netty 的工作原理,并将其应用到实际的网络服务开发中。这个项目可能包含各种示例,如简单的 TCP/UDP ...
这个"Netty实战相关代码-nia-samples-parent.zip"压缩包包含了一个名为"nia-samples-parent-master"的项目,它很可能是Netty实战教程或示例代码的源码仓库。 在深入讲解Netty的知识点之前,我们先了解一下这个项目...
本压缩包包含的是Netty 4.1.15版本的源代码,对于理解Netty的工作原理、学习如何使用和优化Netty具有极高的价值。 Netty的核心概念包括: 1. **NIO(Non-blocking I/O)**: Netty基于Java NIO(非阻塞I/O)构建,...
12. Netty源码分析 - 深入理解Netty的内部实现,如事件处理机制、线程模型等,有助于优化和定制化开发。 总之,Netty通过高效的NIO模型、丰富的编解码器、灵活的线程管理和强大的异常处理能力,为企业级应用提供了...
5. **编码器和解码器**:Netty提供了一系列预定义的编码器和解码器,如StringEncoder、LengthFieldBasedFrameDecoder等,用于在网络数据传输中进行格式转换。 6. **Handler**:自定义的业务逻辑处理器,可以实现...
Netty 是一个高性能、异步事件驱动的...Netty 4.1 的源码学习对于网络编程、分布式系统和高并发应用的开发者来说是一笔宝贵的财富。通过理解并实践其中的设计思想,可以提升开发效率,编写出更高效、更可靠的网络应用。
通过深入阅读 Netty 的源码,我们可以了解到网络编程的底层细节,学习到如何设计高性能、可扩展的网络框架,这对于优化分布式系统和微服务架构非常有帮助。同时,Netty 的设计模式和编程思想也对提升软件设计能力...
通过深入学习 Netty 源码,开发者可以掌握网络编程的高级技巧,理解如何构建高性能的网络应用,并能根据需要定制和优化 Netty。这将对你的职业生涯产生积极影响,尤其是对于从事分布式系统、微服务、游戏服务器等...