前文总结了NIO的内容,有了NIO的一些基础之后,我们就可以来看下Netty。Netty是Java领域的高性能网络传输框架,RPC的技术核心就是网络传输和序列化,所以Netty给予了RPC在网络传输领域巨大的支持。

一个简单的Netty代码实现

网络传输基于的是TCP协议,所以会有服务端和客户端之分,而Netty是网络传输框架,所以一个完整的Netty代码至少是有服务端和客户端的。本文代码基于Netty4.1.15。

服务端:

public class DemoServer {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,workerGroup).
channel(NioServerSocketChannel.class).
childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
ch.pipeline().addLast(new DemoServerHandler());
}
}); ChannelFuture future = serverBootstrap.bind(8899).sync();
future.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
public class DemoServerHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("" + ctx.channel().remoteAddress() + "," + msg);
ctx.channel().writeAndFlush("from server" + UUID.randomUUID());
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}

客户端:

public class DemoClient {
public static void main(String[] args) throws Exception{
EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); try{
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
ch.pipeline().addLast(new DemoClientHandler());
}
}); ChannelFuture channelFuture = bootstrap.connect("localhost",8899).sync();
channelFuture.channel().closeFuture().sync(); }finally {
eventLoopGroup.shutdownGracefully();
}
}
}
public class DemoClientHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("" + ctx.channel().remoteAddress());
System.out.println("client output:" + msg);
ctx.writeAndFlush("from client" + LocalDateTime.now());
} @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String msg = "来自客户端的问候!";
ctx.writeAndFlush(msg);
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}

来看下这个简单的代码做了什么:

1、服务端启动后,客户端先向服务端发起连接建立;

2、连接建立后,触发客户端的channelActive方法,该方法向服务端发出了一条信息,这条信息默认在网络中是会转成字节的形式来传输的,因为TCP的数据传输都是基于字节的,这个过程也叫做编码;

3、服务端收到信息后,会被服务端的Handler,其实就是StringDecoder先做处理,从字节变成了字符,这个过程也叫做解码;

4、此时对于DemoServerHandler来说,信息已经变成了符合自己的String类型,所以channelRead0方法会被调用,输出信息,同时向客户端发出信息,信息又会转成字节的信息传向客户端;

5、客户端收到信息后,会被客户端解码成字符,触发客户端的channelRead0方法,输出客户端地址和收到的信息,再向服务端发送时间戳;

6、循环往复上述3-5,死循环;

模块化

从上述这个简单的DEMO中,我们可以提取出Netty的核心模块:

1、Channel、EventLoop、ChannelFuture

Channel接口:基本的IO操作(bind()/connect()/read()/write())依赖于底层网络传输所提供的原语。在我们这个DEMO中,能看到NioServerSocketChannel和NioSocketChannel,NioServerSocketChannel使用基于NIO选择器的实现来接受新连接,NioSocketChannel使用基于NIO选择器的实现来建立和处理新连接。

EventLoop接口:EventLoop定义了Netty的核心抽象,用于处理连接的生命周期中所发生的事件。EventLoop是协调设计的一部分,采用了两个基本的API:并发和网络编程。在我们这个DEMO中,能看到NioEventLoop,NioEventLoop就是一个Reactor,是整个Netty的一个核心。

ChannelFuture接口:Netty中的所有的IO操作都是异步的,因为一个操作可能不会立即返回,所以我们需要一种用于在之后某个时间点确定其结果的方法。为此,Netty提供了ChannelFuture接口,其addListener()方法注册了一个ChannelFutureListener,以便在某个操作完成是得到通知。

2、ChannelHandler、ChannelPipeline

ChannelHandler接口:从应用程序开发人员的角度来看,ChannelHandler是Netty的主要组件,它充当了所有处理入站和出站数据的应用程序逻辑的容器,因为ChannelHandler的方法是由事件来触发的。在我们这个DEMO中,DemoClientHandler、DemoServerHandler就是两个自定义的ChannelHandler,DemoClientHandler在连接一建立的时候,就触发了channelActive方法,然后DemoServerHandler在channelRead0方法中读取了其传输的信息。

ChannelPipeline接口:ChannelPipeline为ChannelHandler链提供了容器,并定义了用于该链上传播入站和出站事件流的API。当Channel被创建时,它会被自动的分配到它所专属的ChannelPipeline。在我们的DEMO中,一个ChannelInitializer的实例被注册到ServerBootStrap或者BootStrap,当它的initChannel方法被调用的时候,ChannelInitializer将在ChannelPipeline中安装一组自定义的ChannelHandler,最后ChannelInitializer将它自己从ChannelPipeline中移除。

3、ByteBuf

网络数据的基本单位是字节,NIO提供了ByteBuffer作为网络数据的字节容器,但是ByteBuffer本身设计并不优雅,使用繁琐,Netty使用ByteBuf来替代ByteBuffer,在我们的DEMO中,不能直接看到ByteBuf,但是在Netty提供的内置编解码器StringDecoder/StringEncoder中,操作的对象就是ByteBuf。

4、ServerBootStrap、BootStrap

ServerBootStrap和BootStrap是一个非常抽象的概念。ServerBootStrap是Netty创建服务器的辅助类,负责封装服务启动的一系列操作。和ServerBootStrap一样,Bootstrap也是封装客户端向服务端发送请求的一系列操作。

5、Codec

通过Netty发送和接收一个消息的时候,就会发生一次数据转换,入站消息会被解码,也就是从字节转换为原本的形式,如果是出站消息,就会从一种形式变成字节,这个就是编码,编解码的根本原因就是因为网络数据就是一系列的字节。在我们的DEMO中,StringEncoder和StringDecoder就是编解码器。

最后总结一下:

1、通过一个简单的DEMO,介绍了一下Netty,站在应用的角度看了下Netty是如何运行的;

2、从DEMO中提取出Netty的重要的模块,简单介绍一下各个模块,在后续的文章中将详细介绍每个模块组件。

参考资料:

https://netty.io/wiki/user-guide-for-4.x.html

Netty:初识Netty的更多相关文章

  1. DotNetty网络通信框架学习之初识Netty

    p{ text-align:center; } blockquote > p > span{ text-align:center; font-size: 18px; color: #ff0 ...

  2. Netty1:初识Netty

    为什么使用Netty Netty是业界最流行的NIO框架之一,它的健壮性.功能.性能.可定制性.可扩展性在同类框架中都是首屈一指的,它已经得到了成百上千的商用项目的证明.对于为什么使用Netty这个话 ...

  3. Netty(一):初识Netty

    Netty是什么? Netty是由JBOSS提供的一个java开源框架. Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 封装了JDK底 ...

  4. 【Netty】Netty入门之WebSocket小例子

    服务端: 引入Netty依赖 <!-- netty --> <dependency> <groupId>io.netty</groupId> <a ...

  5. Netty学习——Netty和Protobuf的整合(二)

    Netty学习——Netty和Protobuf的整合(二) 这程序是有瑕疵的,解码器那里不通用,耦合性太强,有两个很明显的问题,但是要怎么解决呢?如:再加一个内部类型 Person2,之前的代码就不能 ...

  6. Netty学习——Netty和Protobuf的整合(一)

    Netty学习——Netty和Protobuf的整合 Protobuf作为序列化的工具,将序列化后的数据,通过Netty来进行在网络上的传输 1.将proto文件里的java包的位置修改一下,然后再执 ...

  7. [Netty 1] 初识Netty

    1. 简介 最早接触netty是在阅读Zookeeper源码的时候,后来看到Storm的消息传输层也由ZMQ转为Netty,所以决心好好来研究和学习一下netty这个框架. Netty项目地址:htt ...

  8. Netty 学习 一、初识Netty【原创】

    在过去几年的工作和学习中,比较关注高层次的应用开发,对底层探究较少.实现Web应用的开发,主要依赖Tomcat.Apache等应用服务器,程序员无需了解底层协议,但同样限制了应用的性能和效率.现在开始 ...

  9. 初识Netty

    我们已经了解了Socket通信/IO/NIO/AIO编程,对于通信模型已经有了一个初步的认识,其实我们之前所学习的仅仅是一个模型,如果想把这些真正的用于实际工作中去,其实我们之前所学习的仅仅是一个模型 ...

随机推荐

  1. 在WPF(core版本)中引用外部字体不可用问题说明

    这几天使用WPF写软件,想引用外部字体,于是下载了字体文件: 然后在App.xaml中添加了如下代码: <FontFamily x:Key="Digital-7 Mono"& ...

  2. js实现文字头像的生成

    原文地址:https://www.phyer.cn/article/9277.欢迎大家访问我的博客(●ˇ∀ˇ●) 使用canvas画出文字就好啦 function gen_text_img(size, ...

  3. PHPRAP 1.0.2 发布,修复安装失败 Bug 和优化细节

    PHPRAP,是一个PHP轻量级开源API接口文档管理系统,致力于减少前后端沟通成本,提高团队协作开发效率,打造PHP版的RAP. 更新记录 [修复]修复在MySQL5.5版本下安装数据初始化sql文 ...

  4. 使用MySQL练习增删改查时因为版本问题出现连接错误

    使用MySQL练习增删改查时出现连接错误,错误提示如下: 2020-02-19 19:53:51.088 ERROR 16328 --- [reate-249798694] com.alibaba.d ...

  5. Kubernetes-PersistentVolumeClaim(PVC)介绍

    1 PVC介绍   PVC是用户层面,作为对存储资源的需求申请,主要包括了存储空间大小.访问模式.PV的选择条件.存储类别等信息的设置. 2 PVC的参数详解 2.1 PVC的yaml模板 apiVe ...

  6. 每日一点:git 与 github 区别

    絮絮叨叨在前:以前的公司,都用svn 进行代码管理.最近我那程序猿先生真的受不了我,强迫我使用tortoiseGit. 一开始对于 git 和 github 傻傻分不清,干脆自己整理资料,总结一下. ...

  7. wentiqingdan

    1. Python不用在行尾加分号,也不要用分号将两条命令放在同一行,但加上分号也能执行,不像C/C++分号是必须加的,缺了就会出错. 2. C属于编译型语言,Python属解型语言 编译型的优点是& ...

  8. openwrt 编译常用 luci 插件到固件中

    先更新安装 packages luci ./scripts/feeds update packages ./scripts/feeds install -a -p packages ./scripts ...

  9. ASP.NET Core 中jwt授权认证的流程原理

    目录 1,快速实现授权验证 1.1 添加 JWT 服务配置 1.2 颁发 Token 1.3 添加 API访问 2,探究授权认证中间件 2.1 实现 Token 解析 2.2 实现校验认证 1,快速实 ...

  10. MATLAB神经网络(2) BP神经网络的非线性系统建模——非线性函数拟合

    2.1 案例背景 在工程应用中经常会遇到一些复杂的非线性系统,这些系统状态方程复杂,难以用数学方法准确建模.在这种情况下,可以建立BP神经网络表达这些非线性系统.该方法把未知系统看成是一个黑箱,首先用 ...