Netty系列:No1-初识Netty

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fk002008/article/details/80870649

Netty,之前听过一句话,不会Netty,别说你是Java高级。这玩意到底是啥呢?

各种资料看了下,原来就是一款框架啊。为了网络编程而生。和java中的套接字有得一比。

既然是框架,设计思想很重要。

我们来了解下:

Netty

Netty是一款Java框架,用于快速开发高性能的网络应用,
它封装了网络编程的复杂性.
使用 apache maven作为它的管理工具
Netty是一款框架,设计原则: 每个小点都和它的技术性一样重要,穷奇精妙。

Java既有的网络编程的局限

java.net包只提供了一套使用本地系统套接字库提供的阻塞函数

也就是 创建网络编程需要安装如下的步骤进行:

监听某个端口,创建一个 ServerSocket
ServerSocket serverSocket = new ServerSocket(portNumber) ;
然后 使用 accept方法得到一个 客户端的套接字
Socket clientSocket = serverSocket.accept();

这样clientSocket就和 serverSocket进行通信了
使用 clientSocket的流处理可以进行数据的传输
BufferedReder bi = new BufferedReader(
new InpustStreamReader(clientSocket.getInpu·stStream())
);

PrintWriter pw = new PrintWriter(clientSocket.getOutputStream());

使用流就可以进行处理了

传统的java的套接字的缺陷

我们可以看到这种代码同时只能处理一个连接,如果要管理多个客户端的时候,就要给每个客户端的
socket创建一个线程来处理.
这样问题转换为了多线程。
但是如果连接数目很高的时候,线程直接的管理以及创建,切换等管理遇到的问题就很尖锐了.


扫描二维码关注公众号,回复: 3771022 查看本文章
采用多线程进行处理的特点就是消耗内存
通过多个并发的线程来达到高并发的目的。

Netty的处理

netty使用一个 选择器来进行,使这个多线程的处理转变为单线程的处理
netty使用的是 nio 非阻塞io 的使用 non blocking i/o
这个思想是借鉴与 函数式编程的 例如 nodejs的并发实现,
采用 单线程但是 消耗cpu计算能力来得到的高并发
因此这种机制是 事件驱动型的

java.nio.channels.Selector


异步和事件驱动

nodejs使用 的异步,函数式编程思想,单线程的处理,消耗cpu计算达到 高并发处理

异步: 非阻塞,非阻塞网络调用使我们可以不必等待一个操作完成
nio的选择器使我们能够通过很少的线程便可以监视许多链接上的事件。

从这里引出了 Netty 的 特性 :
异步,模仿的nodejs的处理方式,因此是 事件驱动型的

事件,回调,channel 等等

异步的特性: 事情处理完了要想办法通知主程序

回调函数是一种通知方式。
Netty中的 Future也是一种通知的方式

Netty的核心组件

  1. channel
  2. 回调
  3. Future
  4. 事件和ChannelHandler

channel

channel是java nio 的一个基本构造
表示一个到实体的开放链接,
这个实体可以是:
  • 硬件设备
  • 文件
  • 网路套接字
  • 能够执行 io操作的组件

和其名字一样,表示一个 渠道,管道,和上面的实体链接之后,那么就是上面这些实体的数据的载体。
我们对实体的数据以及实体数据的传出都是用这个channel

回调--ChannelHandler

这个不陌生了,js的异步特性中的回调函数.

所以回调本身表示一个 方法 , 也就是该方法的引用提供给另外一个方法。
在c中可以认为是函数的指针,js中就是函数的句柄,java中函数是存在于对象上的,
因此可以使用包装该函数的接口对象

Netty内部使用 回调来处理事件响应。(监听器注册一个函数,当事件触发的时候就回调一个函数)
Java中回调函数必须通过对象包装,因此Netty是通过这个 接口 ChannelHandler来处理的
该接口中有一个 channelActive方法,这个就是一个回调函数
这个类似于 awt编程中的 ActionLiistener的 actionPerformed函数一样。

可以类比: 当一个channel链接到一个实体的时候,那么同时注册这个channel对应的处理
channelHandler的接口函数,一旦有事件出现的时候,就会调用这个函数进行事件的处理
这个方法的签名是:
public void channelActive(ChannelHandlerContext ctx)

ChannelHandlerContext 就是我们获取当前channel的媒介

Future

Future提供了另外一种在操作完成时候通知应用程序的方式
这个对象可以看作是一个 异步操作结果的占位符。它将在未来某个时刻完成并提供对其结果的访问.

Future 接口

JDK 是提供了Future的
java.util.concurrent.Future 接口,但是它提供的实现是只能手动的检查对应的操作是否完成

ChannelFuture实现类

Netty则是提供了另外一个实现: ChannelFuture , 用于在执行异步操作的时候使用
这个 ChannelFuture的实现是借鉴于 Action Listener的

ChannelFutureListener 监听器

也就是说 ChannelFuture 提供了几种不同的方法可以注册一个或注册多个
ChannelFutureListener的实例,同样监听器有自己的回调方法的---operationComplete()
这个很类似于 actionPerformed方法.

public void operationComplete(ChannelFuture future)

可以想象 这个 ChannelFuture和我们的 awt中的 Button是很类似的
他们都可以注册监听器,监听器中封装了回调方法

每个netty的出站 I/O操作 都将返回一个 ChannelFuture 对象.
这样每个I/O操作都不阻塞.

如下的模式进行操作:
  1. 获取channel
  2. 使用channel异步连接远程节点,得到channelfuture
  3. 使用channelfuture注册监听 channelfuturelistener
  4. 实现listener的回调函数 operationComplete方法


Channel channel = ...
ChannelFuture future = channel.concet (new InetSocketAddress("192.168.0.1",25));
future.addListner(new ChannelFutureListener() {
public void operationComplete( ChannelFuture future) {
if(future.isSuccess()) {
} else {
Throwable cause = future.cause();
}
}
});

我们可以看到每一个 channelfuture都将会注册一个 channelfutureListener
所以该监听提供的回调函数 operationComplete方法的入口参数是 ChannelFuture
也就是说可以识别到底是哪一个future的监听结果

事件和ChannelHandler

Netty是基于事件触发的,会通过各种各样的事件通知我们程序的状态
Netty是一个网络编程框架,事件是安装入站和出站数据流的相关性进行分类的

入站事件
连接已被激活或者连接失活
数据读取
用户事件
错误事件


出站事件
打开或关闭远程节点连接
将数据写入或冲刷套接字

每个事件都被分发给 用户实现的 ChannelHandler接口方法


综合

Netty的异步编程是基于 Future 和 回调函数的
而且是事件驱动的
但是每个事件分配给FutureHandler是更深层次的东西。
因为事件很多,因此Netty提供了很多重要的 FutureHandler
而且在内部,FutureHandler也使用了很多的事件和Future

ChannelFuture和回调是相互补充的机制。
ChannelFutureListener是一个精细的回调

No1 Future , 回调 , ChannelHandler
No2 选择器,事件 , EventLoop

选择器 就是来进行事件派发的操作,Netty将选择器给抽象出来了
而且 为每个 channel 分配一个 EventLoop,用于处理所有事件

EventLoop

EventLoop是一个线程驱动,这个和nodejs的循环事件一样
它将处理一个channel的所有I/o




猜你喜欢

转载自blog.csdn.net/fk002008/article/details/80870649