Channel

在Java中,Channel是一个用于IO操作(特别是NIO,即非阻塞IO)的接口,它提供了一种连接到IO服务(如文件系统或套接字)的开放连接。Channel是Java NIO中的核心组件之一,使得能够以更接近操作系统的方式,高效地进行文件和网络数据的读写操作。Channel类似于传统的流(Stream),但主要区别在于Channel总是双向的,即可读可写。

主要类型

Java NIO中的Channel有几种主要类型,每种类型都适用于不同的场景:

  1. FileChannel:用于文件的数据读写。FileChannel可以通过java.nio.channels.FileChannel类来访问,它可以创建、打开、读取、写入、映射和操作文件。

  2. DatagramChannel:用于UDP(用户数据报协议)网络通信。DatagramChannel可以发送和接收DatagramPacket,支持非阻塞模式。

  3. SocketChannel:用于TCP(传输控制协议)网络通信的客户端。SocketChannel可以连接到TCP网络套接字,并进行数据读写。

  4. ServerSocketChannel:用于TCP网络通信的服务器端。ServerSocketChannel可以监听新的进来的连接,并为每个新连接创建SocketChannel

核心概念

  • 非阻塞模式Channel可以被设置为非阻塞模式,在这种模式下,IO操作不会导致线程暂停执行。这允许单个线程管理多个Channel,从而提高了程序的性能和可伸缩性。

  • 缓冲区(BufferChannelBuffer紧密配合工作。数据从Channel读取到Buffer中,或从Buffer写入到Channel中。Buffer实质上是一块可以写入数据,然后从中读取数据的内存区域。

  • 选择器(SelectorSelector与非阻塞的Channel一起使用,可以监视多个Channel上的事件(如连接打开、数据到达)。这样,单个线程就可以管理多个Channel,从而有效地管理大量的网络连接。

示例代码

以下是一个简单的FileChannel示例,演示了如何使用FileChannel将数据读入ByteBuffer

import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;public class ChannelExample {public static void main(String[] args) {try {// 打开一个文件和一个FileChannelRandomAccessFile file = new RandomAccessFile("data.txt", "rw");FileChannel channel = file.getChannel();// 创建一个BufferByteBuffer buffer = ByteBuffer.allocate(48);// 从Channel读取数据到Bufferint bytesRead = channel.read(buffer);while (bytesRead != -1) {// 切换Buffer从写模式到读模式buffer.flip();while (buffer.hasRemaining()) {System.out.print((char) buffer.get());}// 清空Buffer,准备再次写入buffer.clear();bytesRead = channel.read(buffer);}// 关闭Channel和文件channel.close();file.close();} catch (Exception e) {e.printStackTrace();}}
}

在使用NIO进行网络编程或文件操作时,理解Channel的工作原理及其与BufferSelector的交互是非常重要的,这有助于构建高效、可扩展的IO操作。

为了更深入理解Java NIO中的Channel,让我们扩展到网络通信方面,并探讨如何使用SocketChannelServerSocketChannel进行TCP网络通信。

SocketChannel

SocketChannel是一个可以连接到TCP网络套接字的通道。在客户端,SocketChannel用于建立连接、发送请求和接收响应。

创建和连接

SocketChannel可以以阻塞或非阻塞模式创建。在非阻塞模式下,SocketChannel的连接、读取和写入操作都是非阻塞的。

// 打开SocketChannel
SocketChannel socketChannel = SocketChannel.open();
// 设置为非阻塞模式
socketChannel.configureBlocking(false);
// 连接到服务器
socketChannel.connect(new InetSocketAddress("www.example.com", 80));
读写数据

FileChannel类似,SocketChannel也是通过ByteBuffer进行数据的读写。

// 写数据到SocketChannel
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();while(buf.hasRemaining()) {socketChannel.write(buf);
}// 读数据从SocketChannel
ByteBuffer readBuffer = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(readBuffer);

ServerSocketChannel

ServerSocketChannel用于监听新进来的TCP连接,每个新进来的连接都会创建一个SocketChannel

打开和绑定

在服务器端,首先需要打开ServerSocketChannel,然后绑定到特定端口监听客户端的连接请求。

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9999));
接受连接

服务器端使用accept()方法接受客户端的连接请求。该方法会阻塞直到有新的连接到达。

while(true) {// 接受连接,这个方法会阻塞直到有新连接到达SocketChannel socketChannel = serverSocketChannel.accept();// 使用socketChannel进行读写操作...
}

在非阻塞模式下,accept()方法会立即返回,如果没有新的连接,它将返回null

Selector

Selector是Java NIO中的一个组件,允许单线程处理多个Channel。如果你的应用打开了多个连接(Channel),但每个连接的流量都相对较低,使用Selector可以提高效率。

// 创建Selector
Selector selector = Selector.open();// 将Channel注册到Selector上,并指定感兴趣的事件
socketChannel.register(selector, SelectionKey.OP_READ);while(true) {// 等待感兴趣的事件发生int readyChannels = selector.select();if(readyChannels == 0) continue;// 获取发生事件的SelectionKey集合Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> keyIterator = selectedKeys.iterator();while(keyIterator.hasNext()) {SelectionKey key = keyIterator.next();if(key.isAcceptable()) {// 有新的连接到达// 处理接受新连接...} else if (key.isReadable()) {// 一个Channel变得可读// 从Channel读取数据...}keyIterator.remove();}
}

使用Selector可以使单个线程管理多个输入和输出通道,这种模式被称为“非阻塞IO”或“选择器IO”,大大提高了网络应用的可伸缩性。

Java NIO中的Channel概念不仅限于文件IO和基本的TCP/UDP网络通信,还扩展到更高级的网络协议和数据处理技术。以下是一些高级用法和概念:

Pipe

Java NIO Pipe是两个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。

创建Pipe
Pipe pipe = Pipe.open();
向Pipe写数据
Pipe.SinkChannel sinkChannel = pipe.sink();
String newData = "New data to write to pipe..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();while(buf.hasRemaining()) {sinkChannel.write(buf);
}
从Pipe读数据
Pipe.SourceChannel sourceChannel = pipe.source();
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = sourceChannel.read(buf);

File Locking

FileChannel提供了对文件的锁定机制,可以在操作文件时防止其他进程对其进行访问。

锁定文件区域
// 获取文件Channel
FileChannel channel = FileChannel.open(file, StandardOpenOption.WRITE);// 锁定文件的特定区域
FileLock lock = channel.lock(position, size, false);

在持有锁定时,可以安全地读写文件的指定区域。完成操作后,应释放锁定:

lock.release();

Scatter/Gather

Scatter/Gather是一种I/O模式,用于从Channel中读取或写入数据到多个Buffer。

Scatter读取

在读取时,如果Channel中的数据分散到多个Buffer,这称为Scatter读取。

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body   = ByteBuffer.allocate(1024);ByteBuffer[] bufferArray = { header, body };channel.read(bufferArray);
Gather写入

在写入时,如果将多个Buffer中的数据集中到一个Channel,这称为Gather写入。

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body   = ByteBuffer.allocate(1024);// 写数据到Buffer
header.put(...);
body.put(...);ByteBuffer[] bufferArray = { header, body };channel.write(bufferArray);

Asynchronous Channel

Java 7引入了NIO.2,它支持异步通道(AsynchronousChannel),提供了一种异步的IO操作,可以在大型数据读写操作完成时获得通知,而不是等待操作完成。

异步文件通道(AsynchronousFileChannel

可以用于文件的异步读写。

Path path = Paths.get("file.txt");
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);ByteBuffer buffer = ByteBuffer.allocate(1024);
long position = 0;fileChannel.read(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {// 读操作完成时调用}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {// 读操作失败时调用}
});
异步套接字通道(AsynchronousSocketChannelAsynchronousServerSocketChannel

用于TCP网络通信的异步读写。

AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000));serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel,Void>() {@Overridepublic void completed(AsynchronousSocketChannel client, Void attachment) {// 接受新连接时调用}@Overridepublic void failed(Throwable exc, Void attachment) {// 接受新连接失败时调用}
});

使用异步IO可以提高大规模网络应用的性能和可伸缩性,特别是在处理大量并发连接和大型文件操作时。这种模式允许应用程序在执行长时间运行的IO操作时继续执行其他任务,提高了应用程序的整体效率和响应性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/699809.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis部署方式(一)四种部署方式介绍

redis的四种部署方式&#xff1a; Redis单机模式部署、Redis主从模式部署、Redis哨兵模式部署、Cluster集群模式部署&#xff0c;后面三种&#xff08;主从模式&#xff0c;Sentinel哨兵模式&#xff0c;Cluster模式&#xff09;也可以统称为集群模式。 一、单机 1、缺点&…

XFF伪造 [MRCTF2020]PYWebsite1

打开题目 直接查看源码 看到一个./flag.php 访问一下 购买者的ip已经被记录&#xff0c;本地可以看到flag&#xff0c;那么使用xff或者client-ip伪造一下ip试试 bp抓包 加一个X-Forwarded-For头 得到flag

目标检测新SOTA:YOLOv9问世,新架构让传统卷积重焕生机(附代码)

在目标检测领域,YOLOv9 实现了一代更比一代强,利用新架构和方法让传统卷积在参数利用率方面胜过了深度卷积。 继 2023 年 1 月 YOLOv8 正式发布一年多以后,YOLOv9 终于来了! 我们知道,YOLO 是一种基于图像全局信息进行预测的目标检测系统。自 2015 年 Joseph Redmon、Al…

T-Dongle-S3开发笔记——分区表

参考&#xff1a; ESP32之 ESP-IDF 教学&#xff08;十三&#xff09;—— 分区表_esp32分区表-CSDN博客 分区表 - ESP32 - — ESP-IDF 编程指南 latest 文档 (espressif.com) 分区表是 ESP32 划分内部 flash 闪存的清单&#xff0c;它将 flash 划分为多个不同功能的区域用于…

提取淘宝店铺联系方式的爬虫工具

随着电子商务的快速发展&#xff0c;淘宝成为了许多人购物的首选平台。而对于一些商家来说&#xff0c;获取淘宝店铺的联系方式是非常重要的&#xff0c;以便建立更加直接和有效的沟通渠道。本文将介绍一种基于Python的爬虫工具&#xff0c;可以帮助我们提取淘宝店铺的联系方式…

QT问题 打开Qt Creator发现没有菜单栏

之前不知道按了什么快捷键,当我再次打开Qt Creator时发现菜单栏消失啦 找了许多原因发现:安装有道词典的快捷键Ctrl Alt m 与Qt Creator里的快捷键冲突导致菜单栏被莫名其妙的隐藏 解决方法: 1找到有道词典快捷键 2再次按快捷键 Ctrl Alt m就可以重新显示菜单栏

【Pytorch】从MoCo看无监督对比学习;从SupCon看有监督对比学习

目录 无监督对比学习&#xff1a;Moco文章内容理解代码解释 有监督对比学习&#xff1a;Supervised Contrastive Learning文章内容理解 无监督对比学习&#xff1a;Moco 文章内容理解 以下内容全部来自于&#xff1a;自监督学习-MoCo-论文笔记. 侵删 论文&#xff1a;Momentu…

超平面介绍

超平面公式 (1) 超平面是指n维线性空间中维度为n-1的子空间。它可以把线性空间分割成不相交的两部分。比如二维空间中&#xff0c;一条直线是一维的&#xff0c;它把平面分成了两部分&#xff1b;三维空间中&#xff0c;一个平面是二维的&#xff0c;它把空间分成了两部分。(2…

性能优化——canvas 加载海量图

背景 公司的在线设计稿平台的画板列表页开发时由于数据量不足&#xff0c;未能测出关于画板列表页性能问题&#xff0c;在经过用户一段时间的使用后出现了关于初始化卡顿、缩放卡顿等问题&#xff0c;画板列表页采用了vue-konva 原因 关于画板列表为何卡顿有如下几点原因 1、…

如何用jmeter请求application/octet-stream,image/jpeg

用postman调用时&#xff1a; 用jmeter&#xff1a; 注意上图不要勾选&#xff0c;不然会把所有的内容都以二进制传进去&#xff0c;我们不勾选只传二进制的图片内容&#xff0c;勾选了会把MIME类型、参数名称都转为二进制传进去。会报错。

华为配置WLAN AC和AP之间VPN穿越示例

配置WLAN AC和AP之间VPN穿越示例 组网图形 图1 配置WLAN AC和AP之间VPN穿越示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 企业用户接入WLAN网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff0c;不影响…

Idea依赖爆红解决

Idea依赖爆红问题&#xff0c;确认依赖信息没问题&#xff0c;并且试了网上很多方法都无效的情况下&#xff0c;不妨更换maven的版本试一下&#xff0c;可能会有奇效。

七、矩阵的初等变换

目录 -1. 介绍 0、增广矩阵&#xff1a; 1、初等变换的性质&#xff1a; ​编辑2、矩阵初等变换的分类&#xff1a; 2.1 普通的行阶梯矩阵&#xff1a; 2.2 、行最简形矩阵&#xff1a; 2.3、标准形矩阵&#xff1a; 3、初等变换的定理&#xff1a; 4、初等变换的应用&…

SpringBoot:自定义starter

点击查看&#xff1a;LearnSpringBoot08starter 点击查看&#xff1a;LearnSpringBoot08starterTest 点击查看更多的SpringBoot教程 一、主要流程 1. 先创建空的project 2. 打开空的project 结构 图选中model 点击 3. 创建 model&#xff08;Maven&#xff09;启动器 提…

(九)springmvc+mybatis+dubbo+zookeeper分布式架构 整合 - maven构建ant-framework核心代码Base封装

今天重点讲解的是ant-framework核心代码Base封装过程。 因为涉及到springmvc、mybatis的集成&#xff0c;为了使项目编码更简洁易用&#xff0c;这边将基础的BASE进行封装&#xff0c;其中包括&#xff1a;BaseBean、BaseDao、BaseService、CRUD的基础封装、分页组件的封装、m…

SpringBoot之WebSocket服务搭建

SpringBoot之WebSocket服务搭建 文章目录 SpringBoot之WebSocket服务搭建1.创建SpringBoot工程2. pom.xml中引入依赖3. application.yml配置4. 主启动类5. 编写MyWebSocket服务类6. 编写测试页面 WebSockets 彻底改变了 Web&#xff0c;将笨拙、缓慢的实时交互转变为时尚、低延…

传统推荐算法库使用--mahout初体验

文章目录 前言环境准备调用混合总结 前言 郑重声明&#xff1a;本博文做法仅限毕设糊弄老师使用&#xff0c;不建议生产环境使用&#xff01;&#xff01;&#xff01; 老项目缝缝补补又是三年&#xff0c;本来是打算直接重写写个社区然后给毕设使用的。但是怎么说呢&#xff…

数学家的趣闻轶事65则

目录 前言趣闻轶事65则参考文献 前言 有人的地方就有江湖&#xff0c;有江湖的地方就有故事。数学本身就是一个江湖&#xff0c;这个江湖也充满着血雨腥风和侠骨柔情&#xff0c;至今流传着各种各样的传说&#xff0c;其中不乏”马踏江湖潇潇事“&#xff0c;也有"何当共…

RESTful API的解释及如何使用它构建 web 应用程序

RESTful API&#xff08;Representational State Transferful Application Programming Interface&#xff09;是一种设计 web服务的架构风格&#xff0c;它基于 HTTP 协议和标准的 REST 架构原则。 RESTful API 的关键概念包括&#xff1a; 资源&#xff08;Resources&#x…

adb-连接模拟器和真机操作

目录 1. 连接模拟器&#xff08;夜神模拟器示例&#xff09; 1.1 启动并连接模拟器 1.2 开启调试模式 2. USB连接真机调试 2.1 usb数据线连接好电脑&#xff0c;手机打开调试模式 2.2 输入adb devices检测手机 3. Wifi连接真机调试 3.1 USB连接手机和电脑 3.2 运行 adb…