【Netty】NIO 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathering 操作

简介: 【Netty】NIO 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathering 操作

文章目录

I . 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathering 概念

II . 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathering 示例 ( 客户端 )

III . 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathering 示例 ( 服务器端 )





I . 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathering 概念


1 . 分散 Scattering 对应缓冲区写入 : 通道 ( Channel ) 向 缓冲区数组 中写出数据 , 按照索引从第 0 个缓冲区 ( Buffer ) 开始, 依次写入数据 ;


缓冲区 ( Buffer ) 分散 ( Scattering ) 对应方法 : 这是一类方法 , 有很多 , 这里只举一个例子说明 ;


public long read(ByteBuffer[] dsts) throws IOException;


2 . 聚合 Gathering 对应缓冲区读取 : 通道 ( Channel ) 从 缓冲区数组 中读取数据 , 按照索引从第 0 个缓冲区 ( Buffer ) 开始, 依次读取数据 ;


缓冲区 ( Buffer ) 聚合 ( Gathering ) 对应方法 : 这是一类方法 , 有很多 , 这里只举一个例子说明 ;


public long write(ByteBuffer[] srcs) throws IOException;



分散 Scattering 与 聚合 Gathering 都是 通道 ( Channel ) 对 缓冲区数组 ( Buffer[] ) 进行读写的操作 ;






II . 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathering 示例 ( 客户端 )


客户端需求 : 本节演示代码的重心在服务器端 , 服务器端演示 分散 聚合 的具体操作 , 客户端只是演示 网络套接字 流程 , 这里客户端使用 BIO , 使用 TCP 协议进行简单的数据发送 ;



package kim.hsl.bio;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;
public class TCPClient {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket();
            InetSocketAddress inetSocketAddress =
                    new InetSocketAddress(
                            Inet4Address.getLocalHost(),   //本机IP地址
                            8888                      //端口号
                    );
            System.out.println("客户端开始连接 ...");
            //此处会阻塞等待连接成功
            socket.connect(inetSocketAddress);
            System.out.println("客户端连接成功");
            //连接成功后, 开始执行后续操作
            socket.getOutputStream().write("Hello World".getBytes());
            System.out.println("客户端写出 Hello World 成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}



这是之前的示例中使用过的 , 这里在用一次 , 实现的功能 就是 连接目标 IP 地址的 8888 端口 , 发送 “Hello World” 字符串给服务器 , 之后退出 ;






III . 缓冲区 ( Buffer ) 分散 Scattering 与 聚合 Gathering 示例 ( 服务器端 )


1 . 示例需求 : 服务器端使用多个 缓冲区 ( Buffer ) 组成的数组 , 进行读写数据 , 客户端上传的数据 通过 套接字通道 ( SocketChannel ) 写出到 缓冲区数组中 , 服务器端再使用 文件通道 ( FileChannel ) 将数据写出到本地文件中 ;



2 . 示例分析 :



① 缓冲区数组 : ByteBuffer[] buffers = new ByteBuffer[2]; , 创建一个缓冲区数组 , 将这两个缓冲区数组作为读写操作的载体 , 读取数据时就涉及到了缓冲区的 聚合 操作 , 写出数据时 , 就涉及到了 分散 操作 ;


② 分散 Scattering : socketChannel.read(buffers); , 这里直接将数据读取存放到了 缓冲区数组中 , 是将数据分散放入缓冲区数组 , 涉及到 缓冲区 分散 操作 ;


③ 聚合 Gathering : fcOut.write(buffers); , 这里将两个缓冲区的数据 写出到了文件中 , 将分散的数据输入到一个文件中 , 涉及到 缓冲区 聚合 操作 ;


④ 注意缓冲区翻转操作 : 先读取数据 , 之后必须调用 flip() 方法翻转缓冲区 , 然后再写出数据 , 否则会出错 ;



3 . 示例代码 :


package kim.hsl.nio;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
/**
 * 分散 ( Scattering ) 与 聚合 ( Gathering ) 示例
 *
 * 分散 ( Scattering ) : 通道 ( Channel ) 向 缓冲区数组 中写出数据,
 *                       按照索引从第 0 个缓冲区 ( Buffer ) 开始, 依次写入数据
 * 聚合 ( Gathering ) : 通道 ( Channel ) 从 缓冲区数组 中读取数据,
 *                      按照索引从第 0 个缓冲区 ( Buffer ) 开始, 依次读取数据
 *
 * 使用 服务器套接字通道 ( ServerSocketChannel ) 和 套接字通道 ( SocketChannel ) 进行聚合演示
 * 使用 文件通道 ( FileChannel ) 进行分散演示
 *
 * @author han
 *
 */
public class BufferDemo4 {
    public static void main(String[] args) {
        try {
            //1 . 创建 ServerSocketChannel, 绑定本地端口
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            InetSocketAddress inetSocketAddress = new InetSocketAddress(8888);
            serverSocketChannel.socket().bind(inetSocketAddress);
            //2 . 创建 2 个 ByteBuffer, 并放入数组中
            ByteBuffer[] buffers = new ByteBuffer[2];
            buffers[0] = ByteBuffer.allocate(4);
            buffers[1] = ByteBuffer.allocate(8);
            //3 . ServerSocketChannel 阻塞等待客户端连接, 该方法执行后一直阻塞
            SocketChannel socketChannel = serverSocketChannel.accept();
            //4 . 阻塞读取数据, 将数据读取到 buffers 缓冲区数组中的缓冲区中
            socketChannel.read(buffers);
            //5 . 将两个 缓冲区 flip 翻转一下, position 设置为 0
            buffers[0].flip();
            buffers[1].flip();
            //6 . 将读取到的数据写出到文件中
            FileOutputStream fos = null;
            try {
                //1 . FileChannel 可以从 FileOutputStream 中获取
                fos = new FileOutputStream("file4.txt");
                //2 . 创建 FileChannel , 从 FileInputStream / FileOutputStream 中可以获取到
                //FileChannel 是抽象类 , 实际类型是 FileChannelImpl
                FileChannel fcOut = fos.getChannel();
                //3 .  将读取到的数据写出到文件中
                fcOut.write(buffers);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if(fos != null)
                        fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}




4 . 执行 服务器端 与 客户端 程序 : 一定要按照顺序执行 , 先启动服务器端 , 再启动客户端 ;



① 启动服务器端 : 先运行服务器端 ;


② 启动客户端 : 再运行客户端 ;

客户端开始连接 ...
客户端连接成功
客户端写出 Hello World 成功



③ 查看服务器端文件写出结果 :


image.png

目录
相关文章
|
4月前
|
设计模式
Lettuce的特性和内部实现问题之Netty NIO的性能优于BIO的问题如何解决
Lettuce的特性和内部实现问题之Netty NIO的性能优于BIO的问题如何解决
|
6月前
|
存储 编解码 移动开发
技术笔记:NIO流—理解Buffer、Channel概念和NIO的读写操作
技术笔记:NIO流—理解Buffer、Channel概念和NIO的读写操作
44 1
|
1月前
|
消息中间件 缓存 Java
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
零拷贝技术 Zero-Copy 是指计算机执行操作时,可以直接从源(如文件或网络套接字)将数据传输到目标缓冲区, 而不需要 CPU 先将数据从某处内存复制到另一个特定区域,从而减少上下文切换以及 CPU 的拷贝时间。
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
|
2月前
|
Java
让星星⭐月亮告诉你,Java NIO之Buffer详解 属性capacity/position/limit/mark 方法put(X)/get()/flip()/compact()/clear()
这段代码演示了Java NIO中`ByteBuffer`的基本操作,包括分配、写入、翻转、读取、压缩和清空缓冲区。通过示例展示了`position`、`limit`和`mark`属性的变化过程,帮助理解缓冲区的工作原理。
38 2
|
3月前
|
Java
Netty BIO/NIO/AIO介绍
Netty BIO/NIO/AIO介绍
|
4月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
153 0
|
4月前
|
存储 网络协议 Java
【Netty 神奇之旅】Java NIO 基础全解析:从零开始玩转高效网络编程!
【8月更文挑战第24天】本文介绍了Java NIO,一种非阻塞I/O模型,极大提升了Java应用程序在网络通信中的性能。核心组件包括Buffer、Channel、Selector和SocketChannel。通过示例代码展示了如何使用Java NIO进行服务器与客户端通信。此外,还介绍了基于Java NIO的高性能网络框架Netty,以及如何用Netty构建TCP服务器和客户端。熟悉这些技术和概念对于开发高并发网络应用至关重要。
93 0
|
7月前
|
监控 Java
Java一分钟之-NIO:非阻塞IO操作
【5月更文挑战第14天】Java的NIO(New IO)解决了传统BIO在高并发下的低效问题,通过非阻塞方式提高性能。NIO涉及复杂的选择器和缓冲区管理,易出现线程、内存和中断处理的误区。要避免这些问题,可以使用如Netty的NIO库,谨慎设计并发策略,并建立标准异常处理。示例展示了简单NIO服务器,接收连接并发送欢迎消息。理解NIO工作原理和最佳实践,有助于构建高效网络应用。
94 2
|
7月前
|
Java 应用服务中间件 API
从零手写实现 tomcat-06-servlet bio/thread/nio/netty 池化处理
该文介绍了逐步改进的网络服务器实现,从最初的 BIO 基础版到使用线程池的 BIO+Thread,再到 NIO 版本和 NIO+Thread,最后展示了一个使用 Netty 框架的简洁实现。文章旨在说明如何解决阻塞问题,并对比不同模型的优劣,最终推荐使用 Netty 以简化 NIO 编程。
|
7月前
|
移动开发 编解码 网络协议
用Java的BIO和NIO、Netty来实现HTTP服务器(三) 用Netty实现
用Java的BIO和NIO、Netty来实现HTTP服务器(三) 用Netty实现