Netty入门——springboot框架开发一个简单的服务器端和客户端
Posted 小志的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty入门——springboot框架开发一个简单的服务器端和客户端相关的知识,希望对你有一定的参考价值。
目录
一、加入依赖
-
加入依赖
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.39.Final</version> </dependency>
二、服务器端
2.1、服务器端代码
-
服务器端代码
package com.example.nettytest.netty.day1; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioserverSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.logging.LoggingHandler; /** * @description: * @author: xz */ public class Server public static void main(String[] args) //1、服务端启动器:负责组装netty组件 new ServerBootstrap() //2、添加 EventLoop(事件循环) .group(new NioEventLoopGroup()) //3、选择服务器的 ServerSocketChannel 实现 .channel(NioServerSocketChannel.class) //4、添加服务端处理器 // boss负责处理连接;worker(也就是netty中的child) 负责处理读写,决定了 worker(也就是netty中的child) 能执行哪些操作(handler) .childHandler( // 5. channel 代表和客户端进行数据读写的通道 Initializer 初始化,负责添加别的 handler new ChannelInitializer<NioSocketChannel>() @Override protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception //6、添加具体 handler nioSocketChannel.pipeline().addLast(new LoggingHandler()); nioSocketChannel.pipeline().addLast(new StringDecoder());//将 ByteBuf 转换为字符串 nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter()//自定义handler //处理读事件 @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception // 打印上一步转换好的字符串 System.out.println("msg==========="+msg); ); ) //7、绑定监听端口 .bind(8080);
2.2、服务器端代码解读
-
代码1位置 :服务端启动器:负责组装netty组件
-
代码2位置 :创建 NioEventLoopGroup,可以简单理解为 线程池 + Selector 后面会详细展开;
-
代码3位置:选择服务 Scoket 实现类,其中 NioServerSocketChannel 表示基于 NIO 的服务器端实现,其它实现还有
-
代码4位置:为啥方法叫 childHandler,是接下来添加的处理器都是给 SocketChannel 用的,而不是给 ServerSocketChannel。ChannelInitializer 处理器(仅执行一次),它的作用是待客户端 SocketChannel 建立连接后,执行 initChannel 以便添加更多的处理器;
-
代码5位置:channel代表和客户端进行数据读写的通道 Initializer 初始化,负责添加别的 handler;
-
代码6位置:添加具体 handler;
-
代码7位置: ServerSocketChannel 绑定的监听端口;
三、客户端
3.1、客户端代码
- 客户端代码
package com.example.nettytest.netty.day1;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import java.net.InetSocketAddress;
/**
* @description:
* @author: xz
*/
public class Client
public static void main(String[] args) throws InterruptedException
// 1. 客户端启动器
new Bootstrap()
// 2. 添加 EventLoop(事件循环)
.group(new NioEventLoopGroup())
// 3. 选择客户端的 SocketChannel 实现
.channel(NioSocketChannel.class)
// 4. 添加客户端处理器
.handler(new ChannelInitializer<NioSocketChannel>()
// 在连接建立后被调用
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception
//9. 消息会经过通道 handler 处理,这里是将 String => ByteBuf 发出
nioSocketChannel.pipeline().addLast(new StringEncoder());
)
.connect(new InetSocketAddress("localhost",8080))//5. 连接到服务器
.sync()//6. 等待 connect 建立连接完毕
.channel()//7. 连接对象
.writeAndFlush("hello world !");//8. 发送数据
3.2、客户端代码解读
- 代码1位置 :客户端启动器;
- 代码2位置 :创建 NioEventLoopGroup(事件循环),同 Server服务端;
- 代码3位置 :选择客户 Socket 实现类,NioSocketChannel 表示基于 NIO 的客户端实现,其它实现还有
- 代码4位置 :添加 SocketChannel 的处理器,ChannelInitializer 处理器(仅执行一次),它的作用是待客户端 SocketChannel 建立连接后,执行 initChannel 以便添加更多的处理器;
- 代码5位置 :指定要连接的服务器和端口;
- 代码6位置 :Netty 中很多方法都是异步的,如 connect,这时需要使用 sync 方法等待 connect 建立连接完毕;
- 代码7位置 :获取 channel 对象,它即为通道抽象,可以进行数据读写操作;
- 代码8位置 :入消息并清空缓冲区;
- 代码9位置 :消息会经过通道 handler 处理,这里是将 String => ByteBuf 发出;
数据经过网络传输,到达服务器端,服务器端 5 和 6 处的 handler 先后被触发,走完一个流程
四、服务端和客户端流程梳理
-
流程梳理
五、channel 、msg 、handler 和eventLoop 概念理解
5.1、channel 的理解
- 把 channel 理解为数据的通道
5.2、msg 的理解
- 把 msg 理解为流动的数据,最开始输入是 ByteBuf,但经过 pipeline 的加工,会变成其它类型对象,最后输出又变成 ByteBuf
5.3、handler 的理解
- 把 handler 理解为数据的处理工序
(1)、工序有多道,合在一起就是 pipeline,pipeline 负责发布事件(读、读取完成…)传播给每个 handler, handler 对自己感兴趣的事件进行处理(重写了相应事件处理方法);
(2)、handler 分 Inbound 和 Outbound 两类;
5.4、eventLoop 的理解
- 把 eventLoop 理解为处理数据的工人
(1)、工人可以管理多个 channel 的 io 操作,并且一旦工人负责了某个 channel,就要负责到底(绑定);
(2)、工人既可以执行 io 操作,也可以进行任务处理,每位工人有任务队列,队列里可以堆放多个 channel 的待处理任务,任务分为普通任务、定时任务;
(3)、工人按照 pipeline 顺序,依次按照 handler 的规划(代码)处理数据,可以为每道工序指定不同的工人;
以上是关于Netty入门——springboot框架开发一个简单的服务器端和客户端的主要内容,如果未能解决你的问题,请参考以下文章