网站栏目功能分析,网页禁止访问怎么能打开,做外卖网站,网络推广是做什么工作的目录 一、Hello World
1. 目标
2. 服务器端
3. 客户端
4. 流程梳理
#x1f4a1; 提示
5. 运行结果截图
二、Netty执行流程
1. 流程分析
2. 代码案例
2.1. 引入依赖
2.2. 服务端
服务端
服务端处理器
2.3. 客户端
客户端
客户端处理器
2.4. 代码截图 一、Hel…目录 一、Hello World
1. 目标
2. 服务器端
3. 客户端
4. 流程梳理 提示
5. 运行结果截图
二、Netty执行流程
1. 流程分析
2. 代码案例
2.1. 引入依赖
2.2. 服务端
服务端
服务端处理器
2.3. 客户端
客户端
客户端处理器
2.4. 代码截图 一、Hello World
1. 目标
开发一个简单的服务器端和客户端
客户端向服务器端发送 hello, world服务器仅接收不返回
加入依赖
dependencygroupIdio.netty/groupIdartifactIdnetty-all/artifactIdversion4.1.39.Final/version
/dependency
2. 服务器端
new ServerBootstrap().group(new NioEventLoopGroup()) // 1 .channel(NioServerSocketChannel.class) // 2.childHandler(new ChannelInitializerNioSocketChannel() { // 3protected void initChannel(NioSocketChannel ch) {ch.pipeline().addLast(new StringDecoder()); // 5ch.pipeline().addLast(new SimpleChannelInboundHandlerString() { // 6Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) {System.out.println(msg);}});}}).bind(8080); // 4
代码解读
1 处创建 NioEventLoopGroup可以简单理解为 线程池 Selector 后面会详细展开2 处选择服务 Scoket 实现类其中 NioServerSocketChannel 表示基于 NIO 的服务器端实现其它实现
还有 3 处为啥方法叫 childHandler是接下来添加的处理器都是给 SocketChannel 用的而不是给
ServerSocketChannel。
ChannelInitializer 处理器仅执行一次它的作用是待客户端 SocketChannel 建立连接后执行
initChannel 以便添加更多的处理器
4 处ServerSocketChannel 绑定的监听端口5 处SocketChannel 的处理器解码 ByteBuf String6 处SocketChannel 的业务处理器使用上一个处理器的处理结果 3. 客户端
new Bootstrap().group(new NioEventLoopGroup()) // 1.channel(NioSocketChannel.class) // 2.handler(new ChannelInitializerChannel() { // 3Overrideprotected void initChannel(Channel ch) {ch.pipeline().addLast(new StringEncoder()); // 8}}).connect(127.0.0.1, 8080) // 4.sync() // 5.channel() // 6.writeAndFlush(new Date() : hello world!); // 7
代码解读
1 处创建 NioEventLoopGroup同 Server2 处选择客户 Socket 实现类NioSocketChannel 表示基于 NIO 的客户端实现其它实现还有 3 处添加 SocketChannel 的处理器ChannelInitializer 处理器仅执行一次它的作用是待客户端
SocketChannel 建立连接后执行 initChannel 以便添加更多的处理器
4 处指定要连接的服务器和端口5 处Netty 中很多方法都是异步的如 connect这时需要使用 sync 方法等待 connect 建立连接完毕6 处获取 channel 对象它即为通道抽象可以进行数据读写操作7 处写入消息并清空缓冲区8 处消息会经过通道 handler 处理这里是将 String ByteBuf 发出数据经过网络传输到达服务器端服务器端 5 和 6 处的 handler 先后被触发走完一个流程 4. 流程梳理 提示
一开始需要树立正确的观念
把 channel 理解为数据的通道把 msg 理解为流动的数据最开始输入是 ByteBuf但经过 pipeline 的加工会变成其它类型对象最后
输出又变成 ByteBuf
把 handler 理解为数据的处理工序 工序有多道合在一起就是 pipelinepipeline 负责发布事件读、读取完成...传播给每个
handler handler 对自己感兴趣的事件进行处理重写了相应事件处理方法 handler 分 Inbound 和 Outbound 两类
把 EeventLoop 理解为处理数据的工人 工人可以管理多个 channel 的 io 操作并且一旦工人负责了某个 channel就要负责到底绑定工人既可以执行 io 操作也可以进行任务处理每位工人有任务队列队列里可以堆放多个 channel
的待处理任务任务分为普通任务、定时任务 工人按照 pipeline 顺序依次按照 handler 的规划代码处理数据可以为每道工序指定不同的工
人 5. 运行结果截图 二、Netty执行流程
1. 流程分析 Netty 抽象出两组线程池BossGroup专门负责接收客户端的连接, WorkerGroup专门负责网络的读写BossGroup和WorkerGroup类型都是NioEventLoopGroupNioEventLoopGroup相当于一个事件循环组,这个组中含有多个事件循环每一个事件循环是
NioEventLoop
NioEventLoop表示一个不断循环的执行处理任务的线程每个NioEventLoop都有一个 selector ,
用于监听绑定在其上的 socket 的网络通讯 用于监听绑定在其上的 socket 的网络通讯
NioEventLoopGroup可以有多个线程,即可以含有多个NioEventLoop每个BossNioEventLoop 循环执行的步骤有3步轮询 accept事件处理 accept事件, 与client建立连
接 , 生成 NioSocketChannel ,并将其注册到某 个worker 的NIOEventLoop上的selector处理任务队
列的任务即runAllTasks
每个Worker NIOEventLoop循环执行的步骤
轮询 read, write 事件处理 i/o 事件即read , write事件在对应 NioSocketChannel处理处理
任务队列的任务 即runAllTasks
每个Worker 的NIOEventLoop处理业务时会使用 pipeline(管道), pipeline中包含了channel ,
即通过 pipeline可以获取到对应通道, 管道中维护了很多的处理器
2. 代码案例
2.1. 引入依赖 propertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.targetproject.build.sourceEncodingUTF-8/project.build.sourceEncoding/propertiesdependenciesdependencygroupIdcom.google.protobuf/groupIdartifactIdprotobuf-java/artifactIdversion3.19.1/version/dependencydependencygroupIdio.netty/groupIdartifactIdnetty-all/artifactIdversion4.1.42.Final/version/dependencydependencygroupIdorg.slf4j/groupIdartifactIdslf4j-log4j12/artifactIdversion1.6.1/version/dependencydependencygroupIdorg.slf4j/groupIdartifactIdslf4j-log4j12/artifactIdversion1.6.1/version/dependencydependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion1.2.17/version/dependency/dependencies
2.2. 服务端
服务端
public class NettyServer {public static void main(String[] args) {//创建bossgroupEventLoopGroup bossGroup new NioEventLoopGroup();//创建workerGroupEventLoopGroup workerGroup new NioEventLoopGroup();try {//创建服务器启动对象ServerBootstrap bootstrap new ServerBootstrap();//设置启动的数学bootstrap.group(bossGroup, workerGroup)//设置老板组合工作组.channel(NioServerSocketChannel.class)//设置通道类型.option(ChannelOption.SO_BACKLOG, 128)//设置线程队列的连接数.childOption(ChannelOption.SO_KEEPALIVE, true)//设置保持活动连接状态//设置工作组的通道初始化设置处理器的管道线.childHandler(new ChannelInitializerSocketChannel() {//初始化通道的方法protected void initChannel(SocketChannel channel) throws Exception {System.out.println(客户端 socketChannel 初始化 channel);//处理器管道线中添加处理器channel.pipeline().addLast(new NettyServerHandler());}});System.out.println(服务器启动...);//绑定服务端口返回异步通道返回对象ChannelFuture channelFuture bootstrap.bind(6668).sync();//添加监听channelFuture.addListener(new ChannelFutureListener() {//监听操作完成public void operationComplete(ChannelFuture channelFuture) throws Exception {if (channelFuture.isSuccess()) {System.out.println(监听端口6668成功);} else {System.out.println(监听端口6668失败);}}});//设置异步通道关闭事件channelFuture.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
服务端处理器
public class NettyServerHandler extends ChannelInboundHandlerAdapter{/**读事件客户端发送数据会触发该方法1. ChannelHandlerContext ctx:上下文对象, 含有 管道pipeline , 通道channel, 地址2. Object msg: 就是客户端发送的数据 默认Object*/Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {Channel channel ctx.channel();System.out.println(服务器读取线程 Thread.currentThread().getName() channelchannel);System.out.println(server ctxctx);ByteBuf buf (ByteBuf) msg;System.out.println(客户端发送消息是buf.toString(CharsetUtil.UTF_8));System.out.println(客户端地址channel.remoteAddress());}/**读完毕触发*/Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {//写并且清缓冲区一般讲我们对这个发送的数据进行编码ctx.writeAndFlush(Unpooled.copiedBuffer(hello, 客户端, CharsetUtil.UTF_8));}/*处理异常, 一般是需要关闭通道*/Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.close();}
}
2.3. 客户端
客户端
public class NettyClient {public static void main(String[] args) {//创建事件循环组EventLoopGroup group new NioEventLoopGroup();try {//重建客户端启动类Bootstrap bootstrap new Bootstrap();bootstrap.group(group)//设置循环组.channel(NioSocketChannel.class)//设置通道//设置通道初始化.handler(new ChannelInitializerSocketChannel() {//初始化通道protected void initChannel(SocketChannel channel) throws Exception {//设置管道线上的处理器channel.pipeline().addLast(new NettyClientHandler());}});System.out.println(客户端 ok);//请求连接返回异步结果对象ChannelFuture future bootstrap.connect(127.0.0.1, 6668).sync();//设置异步通道关闭事件future.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();}finally {group.shutdownGracefully();}}
}
客户端处理器
public class NettyClientHandler extends ChannelInboundHandlerAdapter {/*通道就绪就会触发该方法*/Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println(client: ctx);ctx.writeAndFlush(Unpooled.copiedBuffer(hello server, CharsetUtil.UTF_8));}/*通道内有读取事件时候触发*/Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buf (ByteBuf) msg;System.out.println(服务器回复的消息buf.toString(CharsetUtil.UTF_8));System.out.println(服务器地址ctx.channel().remoteAddress());}/*异常*/Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
2.4. 代码截图