编辑
2024-07-26
后端
00
请注意,本文编写于 288 天前,最后修改于 288 天前,其中某些信息可能已经过时。

之前用Netty写过一些简单的应用,包括etakeaway(我的非开源作品)的IM系统,还有xxx水库预测(非开源商业作品)传感器数据对接等。但是一直使用的是最基础的功能,也都是一些并发量不是很大的应用,有点强上的感觉,遂打算系统学习一下netty,最近不是很沉得下心学东西,都是在写自己的小网站,持续跟进导师项目,只能拿出一些零碎的时间沉下心来学习,Netty我不会仔细记录,只会记录学习过程中的一些demo和感悟

第一个demo是echo服务器,刚开始学linux网络编程的时候也是写这个东西,那个时候大一,用c语言,转眼就快大三了

首先是Server代码

java
package org.example.demo1_echo_server.server; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class EchoServer { private final int port; // 监听端口 public EchoServer(int port) { this.port = port; } public void start() throws InterruptedException { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast(new StringDecoder()); p.addLast(new StringEncoder()); p.addLast(new EchoServerHandler()); } }); ChannelFuture f = b.bind(port).sync(); System.out.println("EchoServer started on port " + port); f.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { int port = 8080; new EchoServer(port).start(); } } package org.example.demo1_echo_server.server; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; public class EchoServerHandler extends SimpleChannelInboundHandler<String> { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println("Received message: " + msg); ctx.writeAndFlush("热死了,一点都不好!"); // Echo back the received message to the client } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }

client端

java
package org.example.demo1_echo_server.client; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class EchoClient { private final String host; private final int port; public EchoClient(String host, int port) { this.host = host; this.port = port; } public void start() throws InterruptedException { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast(new StringDecoder()); p.addLast(new StringEncoder()); p.addLast(new EchoClientHandler()); } }); ChannelFuture f = b.connect(host, port).sync(); System.out.println("EchoClient connected to " + host + ":" + port); f.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { String host = "localhost"; int port = 8080; new EchoClient(host, port).start(); } } package org.example.demo1_echo_server.client; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; public class EchoClientHandler extends SimpleChannelInboundHandler<String> { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.writeAndFlush("有一个客户端已经建立连接!"); // Send a message to the server when the channel is active ctx.writeAndFlush("你好,我是yowayimono!"); } @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println("Received echo: " + msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }

简单的观察一下上面的结构,我们可以得到一个大概的Netty的基本组件,总结如下

1. Bootstrap 和 ServerBootstrap

  • Bootstrap:用于客户端配置和启动。它简化了 Netty 客户端的创建过程,负责配置和连接到服务器。

  • ServerBootstrap:用于服务器端配置和启动。它简化了 Netty 服务器的创建过程,负责绑定端口和接受客户端连接。

2. Channel

  • Channel:表示一个开放的连接,可以进行读写操作。它是 Netty 网络操作的核心抽象,对应于一个网络套接字(Socket)或一个能够进行 I/O 操作的组件(如文件)。

3. ChannelHandler

  • ChannelHandler:用于处理入站和出站数据。它是 Netty 应用的业务逻辑处理器,可以实现各种功能,如数据编解码、业务处理等。

4. ChannelPipeline

  • ChannelPipeline:是一个有序的 ChannelHandler 链,每个 Channel 都有一个 ChannelPipeline。数据在 ChannelPipeline 中流动,经过一系列的 ChannelHandler 处理。

5. EventLoop

  • EventLoop:负责处理一个或多个 Channel 的所有 I/O 操作。它是一个事件循环,通常与一个线程关联,负责处理注册到它的 Channel 的事件。

6. ChannelFuture

  • ChannelFuture:表示一个异步 I/O 操作的结果。Netty 中的所有 I/O 操作都是异步的,ChannelFuture 用于获取操作完成的状态和结果。

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!