欢迎关注公众号:【爱编程
如果有需要后台回复2019赠送1T的学习资料哦!!

本文是基于Netty4.1.36进行分析

服务端

Netty服务端的启动代码基本都是如下:

private void start() throws Exception {final EchoServerHandler serverHandler = new EchoServerHandler();/*** NioEventLoop并不是一个纯粹的I/O线程,它除了负责I/O的读写之外* 创建了两个NioEventLoopGroup,* 它们实际是两个独立的Reactor线程池。* 一个用于接收客户端的TCP连接,* 另一个用于处理I/O相关的读写操作,或者执行系统Task、定时任务Task等。*/EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup childGroup = new NioEventLoopGroup();try {//ServerBootstrap负责初始化netty服务器,并且开始监听端口的socket请求ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, childGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {
//                            为监听客户端read/write事件的Channel添加用户自定义的ChannelHandlersocketChannel.pipeline().addLast(serverHandler);}});ChannelFuture f = b.bind().sync();f.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {bossGroup.shutdownGracefully().sync();childGroup.shutdownGracefully().sync();}}

从上图的代码可以总结为以下几个步骤:

1、创建ServerBootStrap实例
2、设置并绑定Reactor线程池:EventLoopGroup,EventLoop就是处理所有注册到本线程的Selector上面的Channel
3、设置并绑定服务端的channel
4、5、创建处理网络事件的ChannelPipeline和handler,网络时间以流的形式在其中流转,handler完成多数的功能定制:比如编解码 SSl安全认证
6、绑定并启动监听端口
7、当轮训到准备就绪的channel后,由Reactor线程:NioEventLoop执行pipline中的方法,最终调度并执行channelHandler

服务端创建时序图

ServerBootStrap引导启动服务端

它就是主要引导启动服务端,工作包括以下:

  • 1.创建服务端Channel
  • 2.初始化服务端Channel
  • 3.将Channel注册到selector
  • 4.端口绑定

1.创建服务端Channel

流程:
首先从用户代码的bind()其实就是AbstractBootstrap.bind(),然后通过反射工厂将用户通过b.channel(NioServerSocketChannel.class)传入的NioServerSocketChannel通过调用底层的jdk的SelectorProvider创建channel,同时也接着创建好对应的ChannelPipeline
详情可以参考下图,自己去查看一下源码:

2.初始化服务端Channel

主要工作如下:

1)设置的option缓存到NioServerSocketChannelConfig里
2)设置的attr设置到channel里
3)保存配置的childOptions,配置的childAttrs 到ServerBootstrapAcceptor里
4)往NioSocketChannel的pipeline中添加一个ServerBootstrapAcceptor

主要的核心源码如下:

 @Overridevoid init(Channel channel) throws Exception {final Map<ChannelOption<?>, Object> options = options0();synchronized (options) {setChannelOptions(channel, options, logger);}final Map<AttributeKey<?>, Object> attrs = attrs0();synchronized (attrs) {for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {@SuppressWarnings("unchecked")AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();channel.attr(key).set(e.getValue());}}ChannelPipeline p = channel.pipeline();final EventLoopGroup currentChildGroup = childGroup;final ChannelHandler currentChildHandler = childHandler;final Entry<ChannelOption<?>, Object>[] currentChildOptions;final Entry<AttributeKey<?>, Object>[] currentChildAttrs;synchronized (childOptions) {currentChildOptions = childOptions.entrySet().toArray(newOptionArray(0));}synchronized (childAttrs) {currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(0));}p.addLast(new ChannelInitializer<Channel>() {@Overridepublic void initChannel(final Channel ch) throws Exception {final ChannelPipeline pipeline = ch.pipeline();ChannelHandler handler = config.handler();if (handler != null) {pipeline.addLast(handler);}ch.eventLoop().execute(new Runnable() {@Overridepublic void run() {pipeline.addLast(new ServerBootstrapAcceptor(ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));}});}});}

小结:
总体如上面工作流程所述。
特别地建议:查看ServerBootstrapAcceptor源码,你可以发现ServerBootstrapAcceptor在channelRead事件触发的时候(也就有客户端连接的时候),把childHandler加到childChannel Pipeline的末尾,设置childHandler的options和attrs,最后把childHandler注册进childGroup

3.将Channel注册到selector

注册过程如下图

小结:
Channel 注册过程所做的工作就是将 Channel 与对应的 EventLoop 关联。

1).每个 Channel 都会关联一个特定的 EventLoop, 并且这个 Channel 中的所有 IO 操作都是在这个 EventLoop 中执行的;

2).当关联好 Channel 和 EventLoop 后, 会继续调用底层的 Java NIO SocketChannel 的 register 方法, 将底层的 Java NIO SocketChannel 注册到指定的 selector 中.

通过这两步, 就完成了 Netty Channel 的注册过程.

4.端口绑定

端口绑定的源码流程基本如下图,详情可以还是你自己读一下源码比较好点。

小结:
其实netty端口绑定是调用 jdk的javaChannel().bind(localAddress, config.getBacklog());进行绑定,然后TCP链路建立成功,Channel激活事件,通过channelPipeline进行传播。

客户端

客户端启动的常规代码如下:

  private void start() throws Exception {/*** Netty用于接收客户端请求的线程池职责如下。* (1)接收客户端TCP连接,初始化Channel参数;* (2)将链路状态变更事件通知给ChannelPipeline*/EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(host,port)).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new EchoClientHandler());}});//绑定端口ChannelFuture f = b.connect().sync();f.channel().closeFuture().sync();} catch (Exception e) {group.shutdownGracefully().sync();}}

流程:

1.用户线程创建Bootstrap实例,通过API设置创建客户端相关的参数,异步发起客户端连接。
2.创建处理客户端连接、I/O读写的Reactor线程组NioEventLoopGroup,默认为CPU内核数的2倍。
3.通过Bootstrap的ChannelFactory和用户指定的Channel类型创建用于客户端NioSocketChannel,它的功能类似于JDK NIO类库提供的SocketChannel
4.创建默认的Channel Handler Pipeline,用于调度和执行网路事件。
5.异步发起TCP连接,判断连接是否成功。如果成功,则直接将NioSocketChannel注册到多路复用器上,监听读操作位,用于数据包读取和消息发送,如果没有立即连接成功,则注册连接监听为到多路复用器,等待连接结果。
6.注册对应的网络监听状态为到多路复用器。
7.由多路复用器在I/O现场中轮询个Channel,处理连接结果。
8.如果连接成功,设置Future结果,发送连接成功事件,触发ChannelPipeline执行。
9.由ChannelPipeline调度执行系统和用户的ChannelHandler,执行逻辑。

源码调用流程如下图:

小结:客户端是如何发起 TCP 连接的?

如下图:

特别提醒:
在AbstractChannelHandlerContext.connect()#findContextOutbound这步操作是返回的结果next其实是头节点,也就是说在下一步next.invokeConnect()这里的next就是头节点,所以最终是调用HeadContext .connect()

总结

本文主要讲述netty服务端和客户端的简单工作流程。
具体服务端与客户端如何通信,以及内存管理等方面的知识下一次再写。

最后

如果对 Java、大数据感兴趣请长按二维码关注一波,我会努力带给你们价值。觉得对你哪怕有一丁点帮助的请帮忙点个赞或者转发哦。
关注公众号【爱编码】,回复2019有相关资料哦。

netty tcp服务端主动断开客户端_【Netty】服务端和客户端相关推荐

  1. python编写ftp客户端_用Python写FTP客户端程序

    0 前言: ftp客户端相信大家都用过,那么我们为什么还要用Python写ftp客户端呢? 我想有两个原因: 一是写出更好的ftp客户端应用程序,方便大家使用: 二是定制一些特殊服务,例如每天定时下载 ...

  2. 微服务跨数据库联合查询_微服务架构下,解决数据库跨库查询的一些思路

    加关注,不迷路! 前言 在服务做微服务改造后,原先单库join查询已经不能满足要求,每个拆分的微服务对应一个数据库实例,而且部署在不同的服务器上,那么解决"跨库查询"就势在必行了. ...

  3. 微服务架构 面向服务型架构_微服务架构听起来像面向服务的架构

    微服务架构 面向服务型架构 我不了解面向服务的体系结构. 我认为这只是那些高度理论化和非常不切实际的软件体系结构模式之一. 换句话说,我认为这是建筑狂热者的梦想. 然后,我读了Martin Fowle ...

  4. netty tcp服务端主动断开客户端_「Netty核心技术」6-ChannelPipeline源码

    ChannelPipeline是Channelhandler的容器,它负责ChannelHandler的管理和事件拦截与调度. 土话: ChannelPipeline就是用来管理Channelhand ...

  5. php守护进程内存溢出,$serv-close($fd); 服务端主动断开客户端有问题!

    'core' => array( 'reactor_num' => 2, // 线程数. 一般设置为CPU核数的1-4倍 'worker_num' => 16, // 工作进程数量. ...

  6. asp.net session 如何知道是哪个浏览器客户端_微服务下的分布式session管理

    享学课堂特邀作者:老顾转载请声明出处! 前言 今天老顾带着大家了解一下session会话在微服务架构中采用的技术方案,以及 企业应用中需要注意的问题. session作用 我们知道在web应用中,we ...

  7. c3p0 服务启动获取连接超时_微服务架构中的熔断、降级

    微服务架构中熔断和降级是保证服务高可用的一项重要功能点,微服务区别于一体化项目的最大区别也再于熔断和降级,很多微服务项目的开发人员对熔断的理解就是当服务不可用的时候,为了让整体服务可以正常运行,需要让 ...

  8. 基于java的ftp客户端_基于Java的FTP客户端软件的设计

    基于的FTP客户端软件的设计(含选题审批表,任务书,开题报告,中期检查表,毕业论文8600字,答辩记录) 摘 要:FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中 ...

  9. 民科微服务照片怎么上传_微服务 (为微信公众号提供服务)

    微服务 面向中小企业的微服务产品提供自动应答菜单.微网站生成与管理.微信CRM系统服务.微信公众平台客服服务等综合性的运营管理标准化服务,是多功能的微信运营管理平台. 微信管家是将企业微信公众账号通过 ...

最新文章

  1. 用matlab让高低音频重叠,音频分帧,叠加后仍有不连续
  2. Decorator pattern
  3. 计算机网络实验二:应用层和传输层网络协议分析
  4. clistctrl 单机空白处 会取消选中_官方默许BUG:无法选中也能被控制?这些秘密很多玩家到现在都没发现!...
  5. 数据结构选择题(c语言)
  6. 评估报告有效期过期了怎么办_托福成绩过期了怎么办?
  7. 下载输入python之小说下载器version2.0
  8. iptables的应用
  9. 网络管理与维护作业4
  10. Java编译运行命令
  11. 创建一个简单的Flash动画
  12. 浙江省二级计算机vfp,浙江省高校计算机等级考试大纲(二级——VisualFoxPro语言程序设计大纲)...
  13. 判断分解的无损连接性和保持函数依赖
  14. 40款非常漂亮的免费下载 HTML5 CSS3 网站模板欣赏
  15. 无刷直流电动机矢量控制(四)——simulink仿真搭建(让电机动起来)
  16. 【图像增强】基于Frangi滤波器实现血管图像增强附matlab代码
  17. matlab 软键盘,(转载)DIY激光虚拟键盘低成本自制【全面讲解二】
  18. UVA10115- Automatic Editing
  19. SCAU 18709 魔法
  20. 将Maven项目直接用Tomcat运行

热门文章

  1. 使用for循环遍历文件
  2. 单选框-复选框重置的方法
  3. 如何设置putty远程登录linux
  4. 上传Android或Java库到Maven central repository(转载)
  5. Hadoop系列之六:分布式文件系统HDFS
  6. 如何在windows xp下使用ntfs权限控制
  7. DV录像带导出一定要用1394
  8. SharePoint 2007部署过程详细图解之一:准备
  9. nginx模型概念和配置文件结构
  10. ASP.NET MVC请求处理管道生命周期的19个关键环节(1-6)