自己关于netty的一些学习笔记

客户端和服务端通过以下方式连接和通信,虽然它们各自获取的SocketChannel对象不同,但它们通过网络连接形成了一个双向通信链路:

客户端部分

selector = Selector.open();
socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", PORT));
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);

这段代码中,客户端创建了一个SocketChannel实例,并尝试连接到指定服务器地址和端口。之后,这个SocketChannel被设置为非阻塞模式,并注册到Selector上,关注OP_READ事件,表明客户端准备好了接收数据。这里的SocketChannel代表了客户端一侧的连接通道。

服务端部分

if(key.isReadable()) {  //发生 OP_READ
    SocketChannel channel = (SocketChannel)key.channel();
    ByteBuffer buffer = (ByteBuffer)key.attachment();
    channel.read(buffer);
    System.out.println("form 客户端 " + new String(buffer.array()));
}

在服务端,当检测到SelectionKey的OP_READ事件就绪时,通过key.channel()反向获取到的SocketChannel对象,实际上是与某个已连接客户端对应的通道。这意味着,虽然服务端可能通过这种方式处理来自多个客户端的连接,每次处理时通过key拿到的SocketChannel是特定于当前正在处理的客户端的。
它们之间的连接与通信
连接建立:当客户端的SocketChannel通过open()和connect()方法成功连接到服务端时,服务端的ServerSocketChannel会接收到新的连接请求,并通过accept()方法创建一个新的SocketChannel来专门处理这个连接。此时,客户端和服务端各自持有一个SocketChannel,它们通过底层的TCP/IP协议栈连接在一起,形成了一条物理通信链路。
数据交换:一旦连接建立,双方就可以通过各自的SocketChannel读写数据。服务端通过上面的代码片段监听到OP_READ事件,意味着有数据可以从客户端的SocketChannel读取;客户端也可以通过类似的逻辑监听读事件来接收服务端的数据,或者直接写入数据到其SocketChannel发送给服务端。
综上所述,虽然客户端和服务端获取的SocketChannel对象在内存中是不同的实例,但它们通过网络连接相互关联,共同构成了客户端与服务端之间数据传输的双向通道。

缓冲区在通信中的桥梁作用

数据封装:缓冲区作为数据的容器,帮助封装待发送的数据,确保数据以合适的块大小进行传输,减少网络操作的次数,提高效率。
边界管理:通过缓冲区的capacity(容量)、position(当前位置)、limit(上界)等属性,可以有效管理数据的读写边界,防止数据溢出或未完全读取。
字节操作:无论是文本还是二进制数据,都可以通过缓冲区进行统一处理,便于进行字节级别的操作和转换。
总之,缓冲区位于客户端和服务器的SocketChannel之间,是数据传输的必要组件,它使得数据在实际网络传输前后有一个暂存和处理的空间,保证了数据的可靠传递和高效处理。

数据流向关系图解述

客户端数据准备:
info.getBytes(): 首先,将要发送的字符串info转换为字节数组。这一步是将人类可读的文本转换为计算机可以直接处理的二进制数据。
缓冲区分配与填充:
ByteBuffer.wrap(info.getBytes()): 然后,使用ByteBuffer.wrap()方法创建一个ByteBuffer实例,并将转换后的字节数组包装进去。这一步骤为数据传输准备了缓冲区,使得数据可以被SocketChannel识别并发送。
数据写入SocketChannel:
socketChannel.write(ByteBuffer): 最后,通过SocketChannel的write方法,将缓冲区中的数据写入到网络中。这个过程实际上是由操作系统完成的,数据从应用层经过传输层(通常是TCP/IP协议栈)封装成网络包,然后通过物理网络发送到服务端。

+------------+       +----------------+       +------------------+       +-------------+
|  Client App|  -->  |ByteBuffer (Wrap)|  -->  |SocketChannel (Write)|  -->  | Network     |
| (info Text)|       |  (info Bytes)   |       |                  |       | (Data Packet)|
+------------+       +----------------+       +------------------+       +-------------+

理解了客户端如何使用ByteBuffer和SocketChannel发送数据后,让我们扩展到服务端,看看整个数据流动的完整过程。服务端的工作主要是接收数据、处理(如果需要),然后可能向客户端响应数据。下面是结合服务端的简化数据流向关系图解:
客户端到服务端数据流向
客户端准备并发送数据:
客户端应用层将信息转换为字节,封装到ByteBuffer,通过SocketChannel写入网络。
网络传输:
封装好的数据包在网络中从客户端传输到服务端。
服务端接收数据:
服务端SocketChannel监听网络,接收到数据包。
ByteBuffer分配与读取:服务端为接收数据分配一个ByteBuffer,通过SocketChannel.read(ByteBuffer)方法从网络读取数据到缓冲区中。
服务端处理与响应(假设服务端简单回显)
数据处理:
服务端解析缓冲区中的数据,可能进行一些逻辑处理或直接准备回显。
服务端响应客户端:
响应数据封装:将响应信息转换为字节数组,然后用ByteBuffer包裹。
通过SocketChannel写回:使用服务端的SocketChannel.write(ByteBuffer)方法将响应数据写回客户端。
完整关系图解述

+------------+       +----------------+       +------------------+       +-------------+       +----------------+       +-------------+
|  Client App|  -->  |ByteBuffer (Wrap)|  -->  |SocketChannel (Write)|  -->  | Network     |  -->  |SocketChannel (Read)|  -->  |ByteBuffer (Read)|  -->  | Server App |
| (info Text)|       |  (info Bytes)   |       |                  |       | (Data Packet)|       |                |       |  (Received Info)|       | (Process/Response)|
+------------+       +----------------+       +------------------+       +-------------+       +----------------+       +-------------+

+------------+       +----------------+       +------------------+       +-------------+
| Server App |  -->  |ByteBuffer (Wrap)|  -->  |SocketChannel (Write)|  -->  | Network     |
| (Response) |       |  (Resp Bytes)   |       |                  |       | (Resp Packet)|
+------------+       +----------------+       +------------------+       +-------------+

这个流程展示了客户端如何通过SocketChannel和ByteBuffer发送数据到服务端,服务端如何接收并处理这些数据,以及如何使用相同的机制响应客户端。整个过程中,ByteBuffer作为数据临时存储的媒介,有效地促进了客户端与服务端之间的数据交换

netty的流程

Netty是一个高性能、异步事件驱动的NIO(非阻塞输入/输出)框架,用于快速开发可维护的高负载网络应用程序。Netty的流程从功能上可以分为服务启动、建立连接、读取数据、业务处理、发送数据、关闭连接以及关闭服务几个阶段。以下是Netty流程的详细解释:

一、服务启动

  1. 初始化

    • 使用ServerBootstrap作为Netty的服务端入口,对BossGroupWorkerGroup进行初始化。BossGroup主要处理客户端的新连接请求(即OP_ACCEPT事件),而WorkerGroup则负责处理IO读写、编解码、业务逻辑等(即OP_READ事件、OP_WRITE事件)。
    • EventLoopGroup是Netty中用于处理IO操作的多线程事件循环器。在服务器端,通常需要创建两个EventLoopGroup:一个用于接收客户端连接(bossGroup),另一个用于处理网络IO操作(workerGroup)。
  2. 绑定端口

    • 服务端启动时会绑定一个端口,作为后续客户端连接入口。
    • 绑定端口时,会在BossGroup中的一个NioEventLoopSelector(多路复用器)上注册一条NioServerSocketChannel通道,后续的连接处理将在该通道中进行。
  3. 注册通道

    • NioEventLoop上的Selector会以不断轮询的方式同时监听每个通道上是否有IO事件发生。
    • 每个通道里都会有一个ChannelPipeline管道,管道里全是Handler,包括管道头Head和管道尾Tail,以及进行IO读写、编解码、业务处理的若干个HandlerHandler也可以自定义,将需要的Handler注册进管道即可。

二、建立连接

  1. 处理连接请求

    • 当服务端收到客户端发来的连接请求时,由于这属于OP_ACCEPT事件,因此在BossGroup中处理。
    • BossGroup管理着若干个NioEventLoop,每个NioEventLoop持有一个线程(类似于线程池中的一组线程并发处理若干个连接请求)。
    • 每个NioEventLoop上会创建一个Selector,一个Selector上可以注册多个通道。
  2. 创建并注册Socket通道

    • Selector监听到OP_ACCEPT事件就绪后,会创建一个NioSocketChannel实例,然后交给ServerBootstrapAcceptor这个Handler
    • ServerBootstrapAcceptor是Netty底层代码注册的,其具体操作是向WorkerGroup中的某个Selector注册刚才创建好的NioSocketChannel。自此,客户端连接请求处理结束。
  3. 连接互通

    • 客户端发出连接请求的同时,会自己创建一条NioSocketChannel通道与服务端的NioSocketChannel进行互通。
    • 连接完成后,由WorkerGroup处理后续的IO操作,不需要BossGroup再参与。

三、读取数据、业务处理与发送数据

  1. 读取数据

    • 当客户端发送数据到服务端时,数据会从客户端的通道传输到WorkerGroup中的对应通道。
    • Head会申请一块堆外内存来缓冲请求内容。缓冲完成后,代表数据已准备好,OP_READ事件已就绪。
    • Selector监听到OP_READ事件就绪后,让持有的线程对事件进行处理。
  2. 业务处理

    • ChannelPipeline中,数据会依次经过注册的Handler进行处理。
    • 开发者可以根据需要自定义Handler来实现特定的业务逻辑。
  3. 发送数据

    • 处理完读事件后,如果需要向客户端发送数据,则会在Handler中处理写事件。
    • 将处理结果写到ByteBuf中,然后执行flush操作将ByteBuf内容写到SocketBuffer中,再通过网卡将数据传回给客户端。

四、关闭连接与关闭服务

  1. 关闭连接

    • 当客户端或服务端需要关闭连接时,会触发关闭连接的操作。
    • Netty会释放与该连接相关的资源,并通知对方连接已关闭。
  2. 关闭服务

    • 当服务端需要关闭服务时,会释放所有资源,并停止所有线程的运行。

以上是Netty的完整流程。Netty通过封装Java NIO的复杂性,提供了易于使用的API,让网络编程变得更加简单和高效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值