Java NIO 的前生今世 之二 NIO Channel 小结

2023-11-18

Java NIO Channel

    通常来说, 所有的 NIO 的 I/O 操作都是从 Channel 开始的. 一个 channel 类似于一个 stream.
java Stream 和 NIO Channel 对比

  • 我们可以在同一个 Channel 中执行读和写操作, 然而同一个 Stream 仅仅支持读或写.

  • Channel 可以异步地读写, 而 Stream 是阻塞的同步读写.

  • Channel 总是从 Buffer 中读取数据, 或将数据写入到 Buffer 中.

Channel 类型有:

  • FileChannel, 文件操作

  • DatagramChannel, UDP 操作

  • SocketChannel, TCP 操作

  • ServerSocketChannel, TCP 操作, 使用在服务器端.
    这些通道涵盖了 UDP 和 TCP网络 IO以及文件 IO.

    基本的 Channel 使用例子:

public static void main( String[] args ) throws Exception
{
    //1 打开 FileChannel
    RandomAccessFile aFile = new RandomAccessFile("/Users/xiongyongshun/settings.xml", "rw");
    FileChannel inChannel = aFile.getChannel();
    //2 从 FileChannel 中读取数据
    ByteBuffer buf = ByteBuffer.allocate(48);
    int bytesRead = inChannel.read(buf);
    while (bytesRead != -1) {
        buf.flip();
        while(buf.hasRemaining()){
            System.out.print((char) buf.get());
        }
        buf.clear();
        bytesRead = inChannel.read(buf);
    }
    aFile.close();
}

FileChannel

    FileChannel 是操作文件的Channel, 我们可以通过 FileChannel 从一个文件中读取数据, 也可以将数据写入到文件中.
注意, FileChannel 不能设置为非阻塞模式.

写入数据

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()) {
    channel.write(buf);
}

关闭

        当我们对 FileChannel 的操作完成后, 必须将其关闭

channel.close(); 

设置 position

long pos = channel.position();
channel.position(pos +123);

文件大小

        我们可以通过 channel.size()获取关联到这个 Channel 中的文件的大小. 注意, 这里返回的是文件的大小, 而不是 Channel 中剩余的元素个数.

截断文件

channel.truncate(1024);

    将文件的大小截断为1024字节.

强制写入

    我们可以强制将缓存的未写入的数据写入到文件中:

channel.force(true);

SocketChannel

    SocketChannel 是一个客户端用来进行 TCP 连接的 Channel.
    创建一个 SocketChannel 的方法有两种:

  • 打开一个 SocketChannel, 然后将其连接到某个服务器中

  • 当一个 ServerSocketChannel 接受到连接请求时, 会返回一个 SocketChannel 对象.

打开 SocketChannel

SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("http://example.com", 80));

关闭

socketChannel.close(); 

读取数据

ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf);

    如果 read()返回 -1, 那么表示连接中断了.

写入数据

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()) {
    channel.write(buf);
}

非阻塞模式

        我们可以设置 SocketChannel 为异步模式, 这样我们的 connect, read, write 都是异步的了.

连接
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("http://example.com", 80));

while(! socketChannel.finishConnect() ){
    //wait, or do something else...    
}

        在异步模式中, 或许连接还没有建立, connect 方法就返回了, 因此我们需要检查当前是否是连接到了主机, 因此通过一个 while 循环来判断.

读写

        在异步模式下, 读写的方式是一样的.
在读取时, 因为是异步的, 因此我们必须检查 read 的返回值, 来判断当前是否读取到了数据.

ServerSocketChannel

        ServerSocketChannel 顾名思义, 是用在服务器为端的, 可以监听客户端的 TCP 连接, 例如:

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9999));
while(true){
    SocketChannel socketChannel =
            serverSocketChannel.accept();

    //do something with socketChannel...
}

打开 关闭

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.close();

监听连接

        我们可以使用ServerSocketChannel.accept()方法来监听客户端的 TCP 连接请求, accept()方法会阻塞, 直到有连接到来, 当有连接时, 这个方法会返回一个 SocketChannel 对象:

while(true){
    SocketChannel socketChannel =
            serverSocketChannel.accept();

    //do something with socketChannel...
}

非阻塞模式

        在非阻塞模式下, accept()是非阻塞的, 因此如果此时没有连接到来, 那么 accept()方法会返回null:

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

serverSocketChannel.socket().bind(new InetSocketAddress(9999));
serverSocketChannel.configureBlocking(false);

while(true){
    SocketChannel socketChannel =
            serverSocketChannel.accept();

    if(socketChannel != null){
        //do something with socketChannel...
        }
}


DatagramChannel

    DatagramChannel 是用来处理 UDP 连接的.

打开

DatagramChannel channel = DatagramChannel.open();
channel.socket().bind(new InetSocketAddress(9999));

读取数据

ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();

channel.receive(buf);

发送数据

String newData = "New String to write to file..."
                    + System.currentTimeMillis();
    
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();

int bytesSent = channel.send(buf, new InetSocketAddress("example.com", 80));

连接到指定地址

        因为 UDP 是非连接的, 因此这个的 connect 并不是向 TCP 一样真正意义上的连接, 而是它会讲 DatagramChannel 锁住, 因此我们仅仅可以从指定的地址中读取或写入数据.

channel.connect(new InetSocketAddress("example.com", 80));


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java NIO 的前生今世 之二 NIO Channel 小结 的相关文章

  • 关于搭建简易广域网私人通信程序(python)一步到位!

    原料 python3 腾讯云服务器 用到的库 socket sys threading time pyinstaller 除pyinstaller外均不需单独安装 首先 默认已经买好云服务器 且安装好了python3 此处使用腾讯云服务器
  • 网络编程之udp学习之udp的多播(组播)和广播案例03

    概述 关于多播 广播这些我Qt相关的文章 也有讲述过 https blog csdn net weixin 44517656 article details 105950817 ip相关知识 https blog csdn net weix
  • JDBC 连接MySQL 数据库并查询数据

    JDBC 连接MySQL 数据库并查询数据 一 Mysql安装 二 JDBC 连接MySQL 一 Eclipse新建项目 二 导入Mysql的包 三 建立数据库并查询数据 一 新建mysql数据库 二 JDBC 连接MySQL 数据库并查询
  • Wireshark使用详解

    文章目录 wireshark简介 抓包原理 抓包 抓包窗口介绍 封包详细信息 Packet Details Pane 过滤信息介绍 显示过滤 抓包过滤 高级功能 数据流追踪 wireshark简介 wireshark是捕获机器上的某一块网卡
  • 什么是节点光端机?总线型光端机有哪些优势?

    节点式光端机又称总线型光端机 其准确的定义是采用单 双纤链路式组网形式的图像传输系统 也被称为链路式光端机 那么 节点式光端机具体是什么呢 总线型光端机又有哪些优势呢 接下来我们就跟随飞畅科技的小编一起来详细了解下吧 什么是节点光端机 节点
  • 【精华】搭建个人Web服务器_LAMP

    目录 项目名称 搭建个人Web服务器 LAMP 1 搭建模式 2 搭建步骤 3 常见问题解决方案 项目名称 搭建个人Web服务器 LAMP 1 搭建模式 LAMP 即Linux系统 Apache服务器 MySQL PHP 2 搭建步骤 第一
  • 老猿学5G扫盲贴:R15/R16中计费架构和计费原则涉及的规范文档

    专栏 Python基础教程目录 专栏 使用PyQt开发图形界面Python应用 专栏 PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一 概述 在R16的32 240文档对应规范为3GPP TS 32 240 V16 1 0
  • 移动通信原理B-------例题解答2

    移动通信原理B例题解答2 移动通信原理B 例题解答2 一 题目 若一发射机发射载频为1850Mhz 一辆汽车以每小时72Km h的速度运动 计算在以下情况下接收机的载波频率 1 汽车沿直线朝向发射机运动 2 汽车沿直线背向发射机运动 3 汽
  • MQTT 控制报文 - PUBLISH发布消息,PUBACK,PUBREC,PUBREL,PUBCOMP - 第6章

    目录 6 1 PUBLISH 发布消息 6 1 1 固定报头 6 1 1 1 DUP重发标志 6 1 1 2 Qos服务质量等级 6 1 1 3 RETAIN保留标志 6 1 2 可变报头 6 1 3 有效载荷 6 2 PUBACK 发布确
  • 西门子PLC常用通信协议以及常用协议的区别(一)

    RS232 是硬件接口 描述 是目前最常用的串行通信接口 RS232 C只是表示RS232的版本 简称都是一样的 特性 标准接口采用9针或者25针D型接口 常用的一般是9针接口 因为大部分连接不需要使用对方的传送控制信号 只需要三条线 即发
  • GitHub标星150K的神仙笔记,3个月肝完成功面进美团定级3-2

    俗话说 不想进大厂的程序员不是好程序员 楼主14年小本毕业 离职也有一段时间了 因为一些原因 休整了一段时间 然后3月初开始准备面试 在上家公司工作之余心里一直有着进大厂的执念 上家公司是智能家居互联网行业的 使用的技术框架有dubbo z
  • MQTT 固定报头 中 剩余长度字段的计算

    剩余长度 简介 位置 固定报头中 从第2个字节开始 剩余长度等于可变报头的长度 10字节 加上有效载荷的长度 剩余长度 Remaining Length 表示当前报文剩余部分的字节数 包括可变报头和负载的数据 剩余长度不包括用于编码剩余长度
  • 计算机网络和因特网的基本认识

    计算机网络和因特网 笔者阅读 计算机网络 自顶向下方法 第七版第一章所作笔记如下 主要为计算机网络和因特网的基本认识 第一章概述笔记入口 第二章应用层笔记入口 第三章运输层笔记入口 第四章网络层数据平面笔记入口 1 什么是因特网 1 1 因
  • The remote endpoint was in state [TEXT_FULL_WRITING]

    使用websocket出现的坑 The remote endpoint was in state TEXT FULL WRITING which is an invalid state for called method websocket
  • URI和URL、URN的作用和区别

    前言 我们都知道URL是使用Web浏览器等访问Web页面时需要输入的网页地址 而对URI URN的认识可能很少 更有甚者会像我一样 把URI与URL搞混 还以为是一个东西的不同别名 其实URI是URL与URN的超集 URI包括URL和URN
  • 网络层(四)

    网络层 我们说过 网络层主要讲的就是ip编址和路由选择算法 更准确的说 应该是网际IP协议 网际IP协议主要说明了各个主机和服务器的ip编址规则 了解IP编址前 我们需要知道IP数据报 IP数据报在网络层中传输 我们看一下IP数据报的结构
  • 关于光纤收发器的一些基本常识介绍

    光纤收发器是网络数据传输中必不可缺少的一种设备 那么 什么是光纤收发器呢 光纤收发器都有什么组成的呢 光纤收发器是怎么分类的呢 光纤收发器有哪些特点呢 光纤收发器在数据传播过程中起到什么作用呢 接下来我们就跟随飞畅科技的小编一起来详细了解下
  • 对TCP/IP的深入浅出归纳【WEB开发者】腾讯认证空间

    前段时间做了一个开发 涉及到网络编程 开发过程比较顺利 但任务完成后始终觉得有一些疑惑 主要是因为对网络协议不太熟悉 对一些概念也没弄清楚 后来 我花了一些时间去了解这些网络协议 现在对TCP IP网络协议有了初步的认识 在这里总结出来 可
  • SSL 和 SocketChannel

    理想情况下 我只需要一个简单的SSLSocketChannel 我已经有一个可以通过普通方式读取和写入消息的组件SocketChannel 但对于其中一些连接 我必须通过网络使用 SSL 然而 这些连接上的操作是相同的 有谁知道免费的SSL
  • PubNub最佳实践:如何管理私人房间?

    我正在学习 pubnub 并阅读了他们的文档 但我只是找不到如何管理多房间聊天框 默认情况下 任何人都可以收听某个频道 订阅和发布都很容易 我想要的是拥有一个主要的公共房间 到目前为止一切都很好 但任何人都应该能够与其他人私下交谈 而不会有

随机推荐

  • 征途服务器文件,如何使用云服务器架设征途

    如何使用云服务器架设征途 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 Linux云服务器一般采用SSH连接方式 使用密
  • Linux杂项设备驱动

    一 概念 杂项设备是一种特殊的字符设备 在linux2 6之后出现 与platform虚拟总线相关 通常嵌套在 platform 总线驱动中 实现复杂的驱动 其主设备号固定为10 设备注册是用主设备号10来调用register chrdev
  • 嵌入式 OpenSSL 常用函数——Base64编码及解码和证书操作

    Base64编码就是把二进制数据转换为可见的ASCII字符 Base64解码是相反的过程 主要函数 1 Base64编码初始化函数 VoidEVP EncodeInit EVP ENCODE CTX ctx 参数ctx IN 用于保存Bas
  • Knuth 洗牌算法

    核心思想 洗牌算法 Knuth shuffle算法 对于有n个元素的数组来说 为了保证洗牌的公平性 应该要能够等概率的洗出n 种结果 举例解释如下 开始数组中有五个元素 在前五个数中随机选一个数与第五个数进行交换 每个数都有五分之一的概率被
  • 抽签小程序(C语言随机数)

    最近班级里需要人员抽签参加活动 闲来无事用java的 Math random 方法 java util Random 写了一个随机抽签的 所以我又了解了一下C语言的随机数获取 C语言的随机数获取 参考 http c biancheng ne
  • 计算机房选址,数据中心机房如何选址 数据中心机房如何日常维护

    导读 众所周知 数据中心机房建设规范标准给出了数据中心机房的建设要求 包括数据中心机房分级与性能要求 机房位置选择及设备布置 环境要求 建筑与结构 空气调节 电气技术 电磁屏蔽 机房布线 机房监控与安全防范 给水排水 消防的技术要求 众所周
  • MySQL如何查看未提交的事务SQL

    点击上方蓝字关注我 MySQL中经常遇到事务中的SQL正在执行或执行完成后未提交 如何找出对应的SQL 1 查看正在执行的SQL 查看事务中正在执行的SQL方式有多种 例如 1 1 通过processlist查看 会话1 执行1个SQL m
  • Mabot机器人趣味视频教程-变速风扇

    如何从炎热的夏天中解脱 利用Mabot制作一个电风扇或许是个好主意 制作电风扇之前 我们需要提前了解一下电风扇的工作原理 电风扇主要是由一个旋转轴带动扇叶进行旋转 我们可以将五孔梁当做扇叶 Mabot的驱动球可以当做旋转轴 然后加上底座和支
  • awk字符串函数(printf格式化输出) -- shell

    awk有许多强大的字符串函数 gsub r s 在整个 0中 用s代替r gsub r s t 在整个t中 用s代替r 替换字符串 index s t 返回s中字符串t的第一位置 未用过 length s 返回s长度 c语言strlen m
  • 题12:字符串匹配Pabinkarp(上)

    package 字符串问题 public class case12 字符串匹配之Pabinkarp public static void main String args String s ABABABA 源字符串 String p BAB
  • 2022年江苏省大学生电子设计竞赛(TI杯)电赛 B题 无人机 省级一等奖记录 “一个摆烂人的独白”

    前期 从大一进校开始 我就参加了学校的创新实验室 遇到了很多很好的老师 但种种原因吧 实验室断代了 我也算搭草台班子 大一开始就作为实验室负责人 开始负责实验室的各项事务 大一寒假的时候 老师让我在校电赛试试无人机 初生牛犊不怕虎 也不知道
  • 在 Flutter 中实现一个浮动导航栏

    此图与正文无关 只是为了好看 写在前面 这段时间一直在学习 Flutter 在 dribble 上看到一张导航栏设计图 就是下面这张 感觉很是喜欢 于是思考着如何在 Flutter 中实现这个效果 设计图作者 Luk Stra k 经过一番
  • Apollo平台计算框架CyberRT

    Cyber RT 框架 Cyber RT Robotic Technology 是一种基于ROS Robot Operating System 的开发框架 专门设计用于构建高性能 实时性要求较高的机器人应用程序 旨在提供一套可靠 高效 灵活
  • Java并发编程必备:分布式锁的选型和性能对比

    当涉及到分布式系统中的并发控制和数据一致性时 分布式锁是一种常见的解决方案 下面我将对几种常见的分布式锁实现原理 实现示例 应用场景以及优缺点进行详细分析 1 基于数据库的分布式锁 实现原理 基于数据库的分布式锁使用数据库的事务机制和唯一索
  • Vue实现点击复制文本功能

    1 功能 在页面中实现点击复制内容到粘贴板的功能 2 安装clipboard npm install clipboard 3 封装工具类 新建clipboard js 内容如下 import Vue from vue import Clip
  • 嵌入式(标准IO)

    嵌入式自学第十三天 1 Linux IO进程课程目的 学习编写linux应用程序 APP 2 Linux文件的种类 常规文件 目录文件 字符文件 块文件 链接文件 相当于windows快捷方式 3 IO的概念 I input 输入设备 比如
  • 关于Python模块shelve存储的对象,改变字典的值时必须将获取的副本赋给一个临时变量的更好解决方法

    文章的关键点 将函数open的参数writeback设置为True就不需要引用一个临时变量 开始文章的叙述 如何将数据存储到文件中 如果需要的是简单的存储方案 模块shelve可替你完成大部分工作 你只需提供一个文件名即可 对于模块shel
  • Vector非线程安全

    Vector的方法加了同步锁 但对于复合操作未加锁 是非线程安全的 如经典的put if absent 线程的安全性包括线程的可见性 有序性 原子性 if vector contains element vector add element
  • Modbus 485继电器开、关、读 串口指令

    以下均为地址01时的命令 开继电器1 01 06 00 00 00 01 48 0A 关继电器1 01 06 00 00 00 00 89 CA 开继电器2 01 06 00 01 00 01 19 CA 关继电器2 01 06 00 01
  • Java NIO 的前生今世 之二 NIO Channel 小结

    Java NIO Channel 通常来说 所有的 NIO 的 I O 操作都是从 Channel 开始的 一个 channel 类似于一个 stream java Stream 和 NIO Channel 对比 我们可以在同一个 Chan