Netty之入门第一步-服务端启动
前言
从需求出发,最原始的jdk代码开始一步步看,再看Netty封装了哪些,每个组件充当了什么样的角色,才是这篇文章的立意。
今天这篇文章我会从传统的写法入手,进一步发展到Netty每个组件的含义,Netty包装了什么。
案例
完整代码看本机netty-study工程
Demo —— 一个服务端和客户端的socket例子
1 | package com.imooc.netty.ch2; |
1 | package com.imooc.netty.ch2; |
Server类里面有两个线程,一个是main线程,一个是客户端的接收处理线程,accept阻塞等待client的链接,每获得一个连接就交给一个 ClientHandler去处理。一直阻塞等待处理客户端的连接和数据
1 | package com.imooc.netty.ch2; |
客户端也是两个线程,一个main线程,一个线程向server发送数据。
Netty对socket的抽象
Netty基本组件,与demo里面对应
ServerBootstrap
ServerBootstrap为Netty服务端的启动辅助类,它提供了一系列的方法用于设置服务启动相关的参数。
EventLoopGroup
NioEventLoopGroup ———— > Thread
这个Thread包括两部分 一个是服务端接口客户端连接的线程,第二个是处理每个连接的读写
client的Socket server的ServerSocket Netty将jdk的socketChannel封装成了NioSocketChannel
运行任务来处理在连接的生命周期内发生的事件是任何网络框架的基本功能。与之相应的编程上的构造通常被称为事件循环 ———— 一个Netty使用了 interface io.netty.channel.EventLoop来适配的术语。主要职责就是处理所有注册到本线程多路复用器Selector上的Channel。
ByteBuf
ByteBuf ———— > IO Bytes
java NIO提供了ByteBuffer作为它的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐。Netty的ByteBuffer替代品是ByteBuf,一个强大的实现,即解决了JDK API的局限性,又为网络应用程序的开发者提供了更好的API。
ChannelHandler
ChannelHandler ———— > Logic
ChannelHandler充当了所有处理入站和出站数据的应用程序逻辑的容器。
ChannelPipeline
Pipeline ———— > Logic Chain
ChannelPipeline为ChannelHandler链提供了容器,并定义了用于在该链上的传播入站和出站事件流的API 。当Cahnnel被创建时,它会被自动地分配到它专属的CahnnelPipeline。
Netty服务端启动标准demo
1 | /* |
Netty服务端启动
第一步:创建ServerBootstrap实例
第二步:设置并绑定Reactor线程池
第一步:创建服务端Channel
第二步:初始化服务端Channel
第三步:注册selector
第四步:端口绑定
创建服务端Channel
bind() [用户代码入口]
initAndRegister()[初始化并注册]
newChannel()[创建服务端Channel]
// todo
反射创建服务端Channel
newSocket()[通过jdk来创建底层jdk channel]
NioServerSocketChannelConfig()[tcp参数配置类]
AbstractNioChannel()
configureBlocking(false)[阻塞模式]
AbstractChannel()[创建id,unsafe,pipeline]
初始化服务端Channel ——- init()
init()[初始化入口]
set ChannelOptions, ChannelAttrs
set ChildOptions, ChildAttrs
config handler[配置服务端pipeline]
add ServerBootstrapAcceptor[添加连接器]
注册selector
AbstractChannel.register(channel)[入口]
this.eventLoop = eventLoop[绑定线程]
register0[实际注册]
doRegister()[调用jdk底层注册]
invokeHandlerAdderIfNeeded()
fireChannelRegistered()[传播事件]
端口绑定
AbstractUnsafe.bind()[入口]
doBind()
javaChannel().bind()[jdk底层绑定]
pipeline.fireChannelActive()[传播事件]
HeadContext.readIfIsAutoRead( )[表示可以读了]
两个问题
问:服务端的socket在哪里初始化?
答:
问:在哪里accept连接?
答: