java 套接字关联的通道_Java 通道教程 – NIO 2.0
# Java 通道教程 – NIO 2.0
> 原文: [https://howtodoinjava.com/java7/nio/java-nio-2-0-channels/](https://howtodoinjava.com/java7/nio/java-nio-2-0-channels/)
通道是继[**缓冲区**](//howtodoinjava.com/java-7/nio/java-nio-2-0-working-with-buffers/ "Java NIO 2.0 : Working With Buffers")之后的`java.nio`的第二项重大创新,我们在我之前的教程中已详细了解到。 通道提供与 I/O 服务的直接连接。 **通道是一种在字节缓冲区和通道另一端的实体(通常是文件或套接字)之间有效传输数据的介质。** 通常,通道与操作系统文件描述符具有一对一的关系。 通道类提供了维持平台独立性所需的抽象,但仍可以对现代操作系统的本机 I/O 能力进行建模。 通道是网关,通过它可以以最小的开销访问操作系统的本机 I/O 服务,而缓冲区是通道用来发送和接收数据的内部端点。
## NIO 通道基础
在层次结构的顶部,有[`Channel`](https://docs.oracle.com/javase/7/docs/api/java/nio/channels/Channel.html "Channel")接口,如下所示:
```java
package java.nio.channels;
public interface Channel
{
public boolean isOpen();
public void close() throws IOException;
}
```
由于依赖底层平台的各种因素,`Channel`实现在操作系统之间存在根本性的差异,因此通道 API(或接口)仅描述了可以完成的工作。 **`Channel`实现通常使用本机代码执行实际工作。 通过这种方式,通道接口使您能够以受控且可移植的方式访问低级 I/O 服务。**
从顶级`Channel`接口可以看到,所有通道只有两个共同的操作:检查通道是否打开(`isOpen()`)和关闭打开的通道(`close()`)。
## 打开通道
众所周知,I/O 分为两大类:**文件 I/O 和流 I/O** 。 因此,通道有两种类型也就不足为奇了:文件和套接字。 `FileChannel`类和`SocketChannel`类用于处理这两个类别。
仅可以通过在打开的`RandomAccessFile`,`FileInputStream`或`FileOutputStream`对象上调用`getChannel()`方法来获得`FileChannel`对象。 您不能直接创建`FileChannel`对象。
```java
RandomAccessFile raf = new RandomAccessFile ("somefile", "r");
FileChannel fc = raf.getChannel();
```
与`FileChannel`相反,套接字通道具有工厂方法来直接创建新的套接字通道。 例如
```java
//How to open SocketChannel
SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("somehost", someport));
//How to open ServerSocketChannel
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind (new InetSocketAddress (somelocalport));
//How to open DatagramChannel
DatagramChannel dc = DatagramChannel.open();
```
上面的方法返回一个相应的套接字通道对象。 它们不是`RandomAccessFile.getChannel()`的新通道的来源。 如果已经存在,则它们返回与套接字关联的通道。 他们从不创造新的渠道。
## 使用通道
正如我们已经学习到缓冲区的教程一样,该教程介绍了通道与`ByteBuffer`对象之间的数据传输。 大多数读/写操作由从下面的接口实现的方法执行。
```java
public interface ReadableByteChannel extends Channel
{
public int read (ByteBuffer dst) throws IOException;
}
public interface WritableByteChannel extends Channel
{
public int write (ByteBuffer src) throws IOException;
}
public interface ByteChannel extends ReadableByteChannel, WritableByteChannel
{
}
```
**通道可以是单向或双向**。 给定的通道类可能实现`ReadableByteChannel`,它定义了`read()`方法。 另一个可能会实现`WritableByteChannel`以提供`write()`。 实现这些接口中的一个或另一个的类是单向的:它只能在一个方向上传输数据。 如果一个类实现两个接口(或扩展两个接口的`ByteChannel`),则它是双向的,可以双向传输数据。
如果您查看通道类,则会发现每个文件和套接字通道都实现了这三个接口。 就类定义而言,这意味着所有文件和套接字通道对象都是双向的。 对于套接字来说,这不是问题,因为它们始终是双向的,但是对于文件来说,这是一个问题。 从`FileInputStream`对象的`getChannel()`方法获得的`FileChannel`对象是只读的,但是在接口声明方面是双向的,因为 **`FileChannel`实现了`ByteChannel`** 。 在这样的通道上调用`write()`会抛出未选中的`NonWritableChannelException`,因为`FileInputStream`总是打开具有只读权限的文件。 因此,请记住,当通道连接到特定的 I/O 服务时,通道实例的特性将受到与其连接的服务的特性的限制。 连接到只读文件的`Channel`实例无法写入,即使该`Channel`实例所属的类可能具有`write()`方法。 程序员要知道如何打开通道,而不要尝试执行底层 I/O 服务不允许的操作。
```java
FileInputStream input = new FileInputStream ("readOnlyFile.txt");
FileChannel channel = input.getChannel();
// This will compile but will throw an IOException
// because the underlying file is read-only
channel.write (buffer);
```
`ByteChannel`的`read()`和`write()`方法将`ByteBuffer`对象作为参数。 每个都返回传输的字节数,该字节数可以小于缓冲区中的字节数,甚至为零。 缓冲区的位置将增加相同的量。 如果执行了部分传输,则可以将缓冲区重新提交给通道以继续传输数据,并从该处停止传输。 重复直到缓冲区的`hasRemaining()`方法返回`false`。
在下面的示例中,我们将数据从一个通道复制到另一个通道(*或从一个文件复制到另一个文件*):
```java
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
public class ChannelCopyExample
{
public static void main(String args[]) throws IOException
{
FileInputStream input = new FileInputStream ("testIn.txt");
ReadableByteChannel source = input.getChannel();
FileOutputStream output = new FileOutputStream ("testOut.txt");
WritableByteChannel dest = output.getChannel();
copyData(source, dest);
source.close();
dest.close();
}
private static void copyData(ReadableByteChannel src, WritableByteChannel dest) throws IOException
{
ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while (src.read(buffer) != -1)
{
// Prepare the buffer to be drained
buffer.flip();
// Make sure that the buffer was fully drained
while (buffer.hasRemaining())
{
dest.write(buffer);
}
// Make the buffer empty, ready for filling
buffer.clear();
}
}
}
```
**通道可以在阻塞或非阻塞模式下运行。** 处于非阻塞模式的通道永远不会使调用线程进入睡眠状态。 所请求的操作要么立即完成,要么返回结果表明未完成任何操作。 只能将面向流的通道(例如套接字和管道)置于非阻塞模式。
## 关闭通道
要关闭通道,请使用其`close()`方法。 与缓冲区不同,**通道在关闭**后不能重新使用。 开放通道表示与特定 I/O 服务的特定连接,并封装了该连接的状态。 关闭通道后,该连接将丢失,并且该通道不再连接任何东西。
**在通道上多次调用`close()`是没有害处的。 随后在关闭通道上对`close()`的调用无济于事,并立即返回。**
可以想到,套接字通道可能需要大量时间才能关闭,具体取决于系统的网络实现。 某些网络协议栈可能会在输出耗尽时阻止关闭。
通道的打开状态可以使用`isOpen()`方法进行测试。 如果返回`true`,则可以使用该通道。 如果为`false`,则该通道已关闭,无法再使用。 尝试读取,写入或执行任何其他需要通道处于打开状态的操作将导致`ClosedChannelException`。
**祝您学习愉快!**
相关文章:

虚拟机ubuntu14.04系统设置静态ip
ubuntu14.04 设置静态ip vim /etc/network/interfaces 原来只有 auto lo iface lo inet loopback 修改成如下: auto lo iface lo inet loopbackauto eth0 iface eth0 inet static #静态ip address 192.168.1.6 #要设置的ip gateway 192.168.1.1 #这…

高职信息安全比赛攻防思路_30.LNGZ2020-30:2020年辽宁省职业院校技能大赛(高职组)“信息安全管理与评估”赛项规程...
12020年辽宁省职业院校技能大赛(高职组)信息安全管理与评估赛项规程一、赛项名称赛项编号:LNGZ2020-30赛项名称:信息安全管理与评估英文名称:Information Security Management and Evaluation赛项组别:高职组赛项归属:…

oracle rac对心跳要求_关于心跳网络引起的Oracle RAC的节点驱逐(不是实例驱逐)...
关于心跳网络引起的Oracle RAC的节点驱逐(不是实例驱逐)问:假设如下场景:4个节点rac,心跳线走的是千m网络交换机,若是该千M网络交换机断电,我想知道crs的驱逐节点的算法是怎么样的?Oracle 大连 GCS 答复&am…

php 字符串数组转数组对象_php怎么将数组转成对象?
php将数组转成对象的方法:1、使用数据类型转换,在数组变量前添加“(Object)”来将数组转成对象。2、先使用json_encode()函数将数组转换为json字符串;然后使用json_decode()函数将json字符串转换成对象。php将数组转成对象有时候数组要转为对…

如何在Win7电脑上增加新磁盘分区?
我们在重装好系统Win7系统后有时会碰到需要新建磁盘分区的情况,这时我们再重装系统进行磁盘分区就有些过于麻烦了,其实我们可以利用Win7系统自身的磁盘管理功能来新建一个磁盘分区。下面好系统重装助手就来介绍一下好系统Win7系统电脑磁盘新建分区的方法…

WIn7下Ubuntu 14.04 安装
1. 在Windows下下载Ubuntu14.04的ISO镜像,解压 2. 打开wubi.exe,填写用户名,密码等相关信息,在这里需要注意的是,磁盘空间最好选到最大(30G),执行安装 3. 按照提示,重启系…

cimiss数据_CIMISS,你太优秀了!
原标题:CIMISS,你太优秀了!本周二的时候小据给大家带来了一位新朋友那便是CIMISS你真的了解它吗?一文读懂CIMISS(戳上面的链接进行回顾)今天我们继续了解一起探讨它能够为我们带来哪些好处天气业务“一站式”数据供给自2014年8月以…

python3 tkinter电子书_python3 tkinter实现添加图片和文本
本文在前面文章基础上介绍tkinter添加图片和文本,在这之前,我们需要安装一个图片库,叫Pillow,这个需要下载exe文件,根据下面图片下载和安装。下载完后直接双击安装exe,默认点击下一步,直到安装完…

序列化和反序列化实现
1. 什么是序列化? 程序员在编写应用程序的时候往往需要将程序的某些数据存储在内存中,然后将其写入文件或是将其传输到网络中的另一台计算机上以实现通讯。这个将程序数据转换成能被存储并传输的格式的过程被称为序列化(serialization&#x…

linux source命令
source filename 与 sh filename 及./filename执行脚本的区别在那里呢?1.当shell脚本具有可执行权限时,用sh filename与./filename执行脚本是没有区别得。./filename是因为当前目录没有在PATH中,所有"."是用来表示当前目录的。2.sh…

centos7 nginx配置php7,centos7安装并配置nginx+php,centos7nginx
centos7安装并配置nginxphp,centos7nginxcentos7安装并配置nginxphp安装nginxyum install nginx设置nginx开启起动systemctl start nginx测试访问http://你的域名或IP/查看nginx安装位置whereis nginxnginx: /usr/sbin/nginx /etc/nginx /usr/share/nginx /usr/shar…

host ntrip 千寻rtk_什么是千寻知寸cors账号?它提供的定位服务精度如何?使用时需要注意哪些问题?...
千寻知寸cors账号FindCM:基于RTK技术的厘米级差分数据播发服务,终端设备收到差分数据后,结合自己的卫星观测数据进行高精度定位解算,在观测环境良好的情况下,统计精度可以达到水平2~5厘米,高程2~8厘米。由于…

python创建图片对应的csv格式_Python:如何从csv文件创建图形节点和边?
你可以用另一个COLATIC和COLATIC来建立一个COLATIC/COLATIC。然后将图“投影”到datetime节点上—如果两个datetime都链接到ColA/ColC节点,则在它们之间创建一个链接。在下面的代码展示了一种创建无向图的方法。我不明白你的例子里的指示是什么意思。在import csvim…

卡尺测量的最小范围_工厂车间里常用的测量仪器使用方法介绍,你都会用吗?...
一、测量器具的分类 测量器具是一种具有固定形态、用以复现或提供一个或多个已知量值的器具。按用途的不同量具可分为以下几类:1. 单值量具只能体现一个单一量值的量具。可用来校对和调整其它测量器具或作为标准量与被测量直接进行比较,如量块、角度量块…
codeblocks使用指南
文章目录目录创建c/c项目调试codeblocks快捷键目录 创建c/c项目 左上角File->new->project,然后在弹出的对话框中找到Console application点击Go,然后不断Next,中间的除了项目名和项目地址其他默认即可。 然后在左侧工程目录中点开main文件即可Coding了。&…

php变量 标签,html标签如何使用php中的变量
html标签中使用php变量,提示:Undefined index: uid in /var/www//list.php,list.php的具体代码如下:require redis.php;for ($i0; $i < ($redis->get("userid")) ; $i){$data[] $redis->hgetall("user:&…

Shell基础命令之echo
echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作用。该命令的一般格式为: echo [ -n ] 字符串其中选项n表示输出文字后不换行;字符串能加引号,也能不加引号。用echo命令输出加引号的字符串时,将字符串原…

mysql中leave和_MySQL数据库之Mysql存储过程使用LEAVE实现MSSQL存储过程中return语法
本文主要向大家介绍了MySQL数据库之Mysql存储过程使用LEAVE实现MSSQL存储过程中return语法 ,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助。DELIMITER $$USE qrsoft_dyj_db$$DROP PROCEDURE IF EXISTS proc_withdraw_approve$$CREATE PR…

cron 工具 每分钟_计划任务 cron和crontab
很多时候,我们需要定时执行某个应用或者某段脚本,在linux上,可以使用cron服务,它有点类似于Windows上的任务计划程序。这篇文章将简单介绍cron的使用。1. crond和crontab首先需要分清楚两个概念:crond和crontab。crond…

Bootstrap学习记录-2.container和table
1. Container Bootstrap中容器类提供了2个类标识:container、container-fluid。 两者的区别在于:container:容器不止有15px的padding,还有一个随着浏览器宽度变化而变化的margin。container-fluid:只有固定的15px的pad…

java中super用来定义父类,Java中super的几种用法及与this的区别
综观目前的 Web 应用,多数应用都具备任务调度的功能。本文由浅入深介绍了几种任务调度的 Java 实现方法,包括 Timer,Scheduler, Quartz 以及 JCron Tab,并对其优缺点进行比较,目的在于给需要开发任务调度的程序员提供有…

1001 A+B
代码链接 PDF链接 首先要说的是这道题的难点是如何把数字输出加入逗号,毕竟数据范围并没有超过Long。当然这个难点也不是问题,将数字转为字符串,C中就有这样的函数,然后再用 %30 这样来控制输出 。 但我最近出于想要建立自己的代码库的想法&a…

pma mysql_Table ‘phpmyadmin.pma_table_uiprefs’ doesn’t exist mysql
Error: #1146 – Table ‘phpmyadmin.pma_table_uiprefs’ doesn’t exist mysqlJust upgrade my ubuntu 14 to 15. all looks good then i go to my localhost phpmyadmin and tried to open database then found a strange error like mysql said: #1146 – Table ‘phpmyadm…

Qt字符编码,创建中文文件
1.代码文件本身编码; 2.Qt中用于控制读入和写出文件系统时的字符编码由QTextCodec::setCodecForLocale()所决定。一般不用设置,Qt跟系统交互时会根据系统的Locale来更改传给系统的参数的编码; //utf8格式 QString str1("你好Hello\r\…

Python 查看本机WiFi密码
http://www.lijiejie.com/python-get-all-saved-wifi-passwords/ 很早以前我写过一个,丢了。 今天偶然看到这篇文章 , 也是很久以前写的,他用的方法太烦了。 dos命令不是可以取本机WiFi密码吗。 #coding:utf-8 import os import re impor…

五连阳回调买入法_“4连阳+1阴”这种股票,吃透主升浪!挣得万贯家财
根据以往的个股表现情况来看,那些即将进入主升浪的个股具有以下几个特点:1、个股前期已经有了一定的涨幅,但向上的步伐比较谨慎,走势比较温和;2、股价所处的位置并不低,有的是一段时期以来的最高位置,有的甚…

java有模糊查询吗,到底Java里的模糊查询语句该怎么写
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼现在String sql"select * from car where carName like %?%";可以查询出结果了,但问题又来了,只能查询出一条结果,代码如下carDao.java页面public ArrayList queryAppoint(String car…

stm32的rxne和idle中断_HAL库的STM32F767的DMA通过IDLE中断接收数据但不能访问
仿真能看到接收缓冲区数组中的数据,但不能访问,如果不访问,再开启DMA接收能正常接收,并且在仿真状态下也能查看。只要访问一次这个数组,下一次开启DMA接收后就不能接收数据了。原代码如下:if(rx_end 1){rx…

使用OpenRowSet操作Excel Excel导入数据库
使用 OpenRowSet 和 OpenDataSource 访问 Excel 97-2007 测试文件:D:\97-2003.xls和D:\2007.xlsx,两个文件的内容是一模一样的。 测试环境:SQL Server 2000 / 2005。 ---------------------------------------------------------------------…

在Windows上搭建Git Server
Git在版本控制方面,相比与SVN有更多的灵活性,对于开源的项目,我们可以托管到Github上面,非常方便,但是闭源的项目就会收取昂贵的费用。 那么私有项目,如何用Git进行代码版本控制呢?我们可以自己…