Netty第一部

2023-11-02 04:28
文章标签 netty 第一部

本文主要是介绍Netty第一部,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、select和epoll原理分析

外设设备网卡、鼠标、键盘等通过总线写到内存中,中间就有DMA拷贝,操作系统怎么知道内存中有数据了,这就需要操作系统通过中断机制确定,如果有中断信号过来,cpu会首先打断用户程序执行,响应硬件的程序的信号,然后再恢复用户程序的执行;不同外设设备对应的驱动程序不同,发送的中断信号也就不同,操作系统根据对应信号做出相应的处理

1、操作系统如何处理中断请求

内核和设备驱动是通过中断方式来处理的。所谓中断,可以理解当设备上有数据到达时,会给cpu的相关引脚上发一个电压变化,以通知cpu来处理数据;硬件产生的信号需要cpu立马处理,否则数据可能丢失

网络模块比较耗时,中断时会过度占用cpu,导致cpu无法响应其它设备,因此在Linux中段处理函数分上半部和下半部,上半部通知cpu,下半部响应

2、进程阻塞

操作系统为了支持多任务,实现进程调度功能,会把进程分为“运行”和“等待”等几种状态。运行状态是获取cpu使用权,正在执行的代码是运行状态;等待状态是阻塞状态,详情参照下图(个人理解)

3、内核接收网络数据

一旦有cpu响应中断操作就会拷贝数据到内存,经过协议层的解析到socket应用层就有了数据,就会唤醒进程A,重新进入到工作队列中

4、同时监视多个socket的简单方法

select实现思路很直接。假如程序同时监视socket1、socket2、socket3,那么调用select之后,操作系统把进程A分别加入到这三个socket的等待列表中,当任何一个socket收到数据,都会中断程序唤醒进程A,所有的socket的等待队列中的进程A都会被移除,加入到工作队列中

如上图所示,进程A只知道Socket有数据过来,并不知道哪些Socket有数据,所以就需要遍历Socket列表;并且处于遍历的性能考虑,select最大只能监视1024个Socket

5、epoll的原理

当执行epoll_create方法时,内核会创建一个eventpoll对象;当Socket收到数据后,中断程序会操作eventpoll对象,而不直接操作进程;中断程序会给rdlist引用收到的数据Socket2、Socket3,当执行epoll_wait,如果rdlist已经引用了Socket,那么epoll_wait直接返回,如果rdlist为空,阻塞进程

当Socket接收到数据,中断程序一方面修改rdlist,另一个方面唤醒 eventpoll等待队列的线程,线程A回到工作队列中去,由于rdlist引用了接收了数据的Socket,所以不用对所有的进行遍历

二、Netty基础

1、Netty的组件

  1. Bootstrap是Netty框架的启动类和主入口类,分为客户端类Bootstrap和服务器类ServerBootstrap两种。
  2. EventLoop暂时可以看成一个线程、EventLoopGroup 自然就可以看成线程组。
  3. Channel是Java NIO的一个基本构造。
  4. ChannelHandler和ChannelPipeline:每个事件都可以被分发给 ChannelHandler 类中的某个用户实现的方法,既然事件分为 入站和出站,用来处理事件的 ChannelHandler 也被分为可以处理入站事件的 Handler 和出站 事件的 Handler,当然有些 Handler 既可以处理入站也可以处理出站;这些 ChannelHandler 都放在 ChannelPipeline 中统一管理
  5. ChannelFuture:异步获取结果的类,类似于JDK的java.util.concurrent.Future类

2、使用示例

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId<version>4.1.42.Final </version><scope>compile</scope>
</dependency>

服务端

public class EchoServer  {private static final Logger LOG = LoggerFactory.getLogger(EchoServer.class);private final int port;public EchoServer(int port) {this.port = port;}public static void main(String[] args) throws InterruptedException {int port = 9999;EchoServer echoServer = new EchoServer(port);LOG.info("服务器即将启动");echoServer.start();LOG.info("服务器关闭");}public void start() throws InterruptedException {/*线程组*/EventLoopGroup group  = new NioEventLoopGroup();try {/*服务端启动必备*/ServerBootstrap b = new ServerBootstrap();b.group(group).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new EchoServerHandler());}});/*异步绑定到服务器,sync()会阻塞到完成*/ChannelFuture f = b.bind().sync();LOG.info("服务器启动完成。");/*阻塞当前线程,直到服务器的ServerChannel被关闭*/f.channel().closeFuture().sync();} finally {group.shutdownGracefully().sync();}}}

客户端

public class EchoClient {private final int port;private final String host;public EchoClient(int port, String host) {this.port = port;this.host = host;}public void start() throws InterruptedException {/*线程组*/EventLoopGroup group  = new NioEventLoopGroup();try {/*客户端启动必备,和服务器的不同点*/Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class)/*指定使用NIO的通信模式*//*指定服务器的IP地址和端口,和服务器的不同点*/.remoteAddress(new InetSocketAddress(host,port))/*和服务器的不同点*/.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new EchoClientHandler());}});/*异步连接到服务器,sync()会阻塞到完成,和服务器的不同点*/ChannelFuture f = b.connect().sync();f.channel().closeFuture().sync();/*阻塞当前线程,直到客户端的Channel被关闭*/} finally {group.shutdownGracefully().sync();}}public static void main(String[] args) throws InterruptedException {new EchoClient(9999,"127.0.0.1").start();}
}

服务端的ChannelHandler

public class EchoServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf in = (ByteBuf)msg;System.out.println("server accept :" + in.toString(CharsetUtil.UTF_8));ctx.writeAndFlush(in);//ctx.close();}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("连接已建立");super.channelActive(ctx);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}

客户端的ChannelHandler

public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {/*读取到网络数据后进行业务处理,并关闭连接*/@Overrideprotected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {System.out.println("client Accept"+msg.toString(CharsetUtil.UTF_8));//关闭连接///ctx.close();}/*channel活跃后,做业务处理*/@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ctx.writeAndFlush(Unpooled.copiedBuffer("Hello,Netty",CharsetUtil.UTF_8));
//        ctx.pipeline().write()
//        ctx.channel().write()ctx.alloc().buffer();}
}

这篇关于Netty第一部的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/328098

相关文章

环信_Android_第一部_JAR包集成

自己新建 project...不用easeui的包,太不友好了..全部自己解封.自己写 个是在要Android studio 3.3.2版本中测试有效在android7和8(API24,25,26,27)四个个版本中有效. 如果到了Adnroid9(API28,Q)会有so报错.在AndroidMaifest.xml有两处用☆标出来 注意三点. 1:复制两个文件夹文件 libs.av 是

【Netty】netty中都是用了哪些设计模式

对于工程师来说,掌握并理解运用设计模式,是非常重要的,但是除了学习基本的概念之外,需要结合优秀的中间件、框架源码学习其中的优秀软件设计,这样才能以不变应万变。 单例模式 单例模式解决的对象的唯一性,一般来说就是构造方法私有化、然后提供一个静态的方法获取实例。 在netty中,select用于处理CONTINUE、SELECT、BUSY_WAIT 三种策略,通过DefaultSelectStra

Java语言的Netty框架+云快充协议1.5+充电桩系统+新能源汽车充电桩系统源码

介绍 云快充协议+云快充1.5协议+云快充1.6+云快充协议开源代码+云快充底层协议+云快充桩直连+桩直连协议+充电桩协议+云快充源码 软件架构 1、提供云快充底层桩直连协议,版本为云快充1.5,对于没有对接过充电桩系统的开发者尤为合适; 2、包含:启动充电、结束充电、充电中实时数据获取、报文解析、Netty通讯框架、包解析工具、调试器模拟器软件等; 源码合作 提供完整云快充协议源代码

Netty源码解析9-ChannelHandler实例之MessageToByteEncoder

MessageToByteEncoder框架可见用户使用POJO对象编码为字节数据存储到ByteBuf。用户只需定义自己的编码方法encode()即可。 首先看类签名: public abstract class MessageToByteEncoder<I> extends ChannelOutboundHandlerAdapter 可知该类只处理出站事件,切确的说是write事件

Netty源码解析8-ChannelHandler实例之CodecHandler

编解码处理器作为Netty编程时必备的ChannelHandler,每个应用都必不可少。Netty作为网络应用框架,在网络上的各个应用之间不断进行数据交互。而网络数据交换的基本单位是字节,所以需要将本应用的POJO对象编码为字节数据发送到其他应用,或者将收到的其他应用的字节数据解码为本应用可使用的POJO对象。这一部分,又和JAVA中的序列化和反序列化对应。幸运的是,有很多其他的开源工具(prot

Netty源码解析7-ChannelHandler实例之TimeoutHandler

请戳GitHub原文: https://github.com/wangzhiwubigdata/God-Of-BigData TimeoutHandler 在开发TCP服务时,一个常见的需求便是使用心跳保活客户端。而Netty自带的三个超时处理器IdleStateHandler,ReadTimeoutHandler和WriteTimeoutHandler可完美满足此需求。其中IdleSt

Netty源码解析6-ChannelHandler实例之LoggingHandler

LoggingHandler 日志处理器LoggingHandler是使用Netty进行开发时的好帮手,它可以对入站\出站事件进行日志记录,从而方便我们进行问题排查。首先看类签名: @Sharablepublic class LoggingHandler extends ChannelDuplexHandler 注解Sharable说明LoggingHandler没有状态相关变量,

Netty源码解析5-ChannelHandler

ChannelHandler并不处理事件,而由其子类代为处理:ChannelInboundHandler拦截和处理入站事件,ChannelOutboundHandler拦截和处理出站事件。ChannelHandler和ChannelHandlerContext通过组合或继承的方式关联到一起成对使用。事件通过ChannelHandlerContext主动调用如fireXXX()和write(msg)

Netty源码解析4-Handler综述

Netty中的Handler简介 Handler在Netty中,占据着非常重要的地位。Handler与Servlet中的filter很像,通过Handler可以完成通讯报文的解码编码、拦截指定的报文、 统一对日志错误进行处理、统一对请求进行计数、控制Handler执行与否。一句话,没有它做不到的只有你想不到的 Netty中的所有handler都实现自ChannelHandler接口。按照输入

Netty源码解析3-Pipeline

请戳GitHub原文: https://github.com/wangzhiwubigdata/God-Of-BigData Channel实现概览 在Netty里,Channel是通讯的载体,而ChannelHandler负责Channel中的逻辑处理。 那么ChannelPipeline是什么呢?我觉得可以理解为ChannelHandler的容器:一个Channel包含一个Chan