目录

Part 1. Define

Part 2. Implementation

1. Channel

2. FileChannel

3. ServerSocketChannel

4. SocketChannel

5. ServerSocket

Part 3. Demo

1. FileChannel

2. ServerSocketChannel


Part 1. Define

Difference between NIO's Channel and Stream:

1 NIO Channel can both read and write from / to channel, but the read and write of the stream is usually one-way.

2 Channels can be read and written asynchronously.

3  The data in the channel must always be read to a Buffer first, or always written from a Buffer.

A channel represents an open connection to an entity such as a hardware device, a file, a network socket, or a program component that is capable of performing one or more distinct I/O operations, for example reading or writing.

A channel is either open or closed.  A channel is open upon creation, and once closed it remains closed.  Once a channel is closed, any attempt to invoke an I/O operation upon it will cause a 'ClosedChannelException' to be thrown.  Whether or not a channel is open may be tested by invoking its 'isOpen' method.

Channels are, in general, intended to be safe for multithreaded access as described in the specifications of the interfaces and classes that extend and implement this interface.

Part 2. Implementation

There are four main implementations of Channel in java like 'FileChannel', 'SocketChannel', 'ServerSocketChannel' and 'DatagramChannel':

* FileChannel                   read and write from/to file

* DatagramChannel         read and write from/to file UDP

* SocketChannel              read and write from/to TCP

* ServerSocketChannel   Listen new tcp connect like Web Server. Every new connect will create a SocketChannel

1. Channel

1) What's Channel?

Channel is the super interface of 'channel in NIO' that define the common method.

2) What's the core method?

1. boolean isOpen();

return whether or not this channel is open.

2. void close()

1) Closes this channel.

1. After a channel is closed, any further attempt to invoke I/O operations upon it will cause a {@link ClosedChannelException} to be thrown.

2. If this channel is already closed then invoking this method has no effect.

3. This method may be invoked at any time.  If some other thread has already invoked it, however, then another invocation will block until the first invocation is complete, after which it will return without effect.

2. FileChannel

1) What is FileChannel?

A channel for reading, writing, mapping, and manipulating a file.

A file channel is a 'SeekableByteChannel'(super class) that is connected to a file. It has a current position within its file which can be both position() queried and position(long) modified. The file itself contains a variable-length sequence of bytes that can be read and written and whose current size can be queried.  The size of the file increases when bytes are written beyond its current size; the size of the file decreases when it is truncated. The file may also have some associated metadata such as access permissions, content type, and last-modification time; this class does not define methods for metadata access.

2) How to get a FileChannel and What feature does it support?

1. A file channel is created by invoking one of the open methods defined by this class. A file channel can also be obtained from an existing FileInputStream, FileOutputStream, or RandomAccessFile object by invoking that object's getChannel method, which returns a file channel that is connected to the same underlying file. Where the file channel is obtained from an existing stream or random access file then the state of the file channel is intimately connected to that of the object whose getChannel method returned the channel.

2. Changing the channel's position, whether explicitly or by reading or writing bytes, will change the file position of the originating object, and vice versa. Changing the file's length via the file channel will change the length seen via the originating object, and vice versa.  Changing the file's content by writing bytes will change the content seen by the originating object, and vice versa.

3. "open-mode" - At various points this class specifies that an instance that is "open for reading," "open for writing," or "open for reading and writing" is required.  A channel obtained via the  getChannel method of a FileInputStream instance will be open for reading.  A channel obtained via the getChannel method of a  FileOutputStream instance will be open for writing.  Finally, a channel obtained via the getChannel method of a RandomAccessFile instance will be open for reading if the instance was created with mode "r" and will be open for reading and writing if the instance was created with mode "rw".

4."append-mode" - A file channel that is open for writing may be in 'append mode', for example if it was obtained from a file-output stream that was created by invoking the FileOutputStream(java.io.File,boolean), FileOutputStream(File,boolean) constructor and passing 'true' for the second parameter.  In this mode each invocation of a relative write operation first advances the position to the end of the file and then writes the requested data.  Whether the advancement of the position and the writing of the data are done in a single atomic operation is system-dependent and therefore unspecified.

3) What operation does FileChannel support?

In addition to the familiar read, write, and close operations of byte channels, this class defines the following file-specific operations:

1. Bytes may be read(ByteBuffer, long) read or write(ByteBuffer, long) written at an absolute position in a file in a way that does not affect the channel's current position.

2. A region of a file may be mapped directly into memory; for large files this is often much more efficient than invoking the usual read or write methods.

3. Updates made to a file may be forced out to the underlying storage device, ensuring that data are not lost in the event of a system crash.

4. Bytes can be transferred from a file to some other channel, and vice versa, in a way that can be optimized by many operating systems into a very fast transfer directly to or from the filesystem cache.

5. A region of a file may be locked against access by other programs.

6. File channels are safe for use by multiple concurrent threads.

4) What's the Core Method?

// Opens or creates a file, returning a file channel to access the file.
FileChannel open(...);// Reads a sequence of bytes from this channel into the given buffer.
int read(ByteBuffer dst);// Writes a sequence of bytes to this channel from the given buffer.
int write(ByteBuffer src);// Returns this channel's file position.
long position();// Returns the current size of this channel's file.
long size();

3. ServerSocketChannel

1) What is ServerSocketChannel?

A selectable channel for stream-oriented listening sockets.

A server-socket channel is created by invoking the open() method of this class.  It is not possible to create a channel for an arbitrary, pre-existing ServerSocket. A newly-created server-socket channel is open but not yet bound.  An attempt to invoke the accept() method of an unbound server-socket channel will cause a 'NotYetBoundException' to be thrown. A server-socket channel can be bound by invoking one of the  bind(java.net.SocketAddress,int) methods defined by this class.

Socket options are configured using the setOption(SocketOption,Object) method. Server-socket channels support the following options:

Socket options

Socket options are configured using the setOption(SocketOption,Object) method. Server-socket channels support the following options:

1 - java.net.StandardSocketOptions.SO_RCVBUF (The size of the socket receive buffer)

2 - java.net.StandardSocketOptions.SO_REUSEADDR (Re-use address)

2) What's the Core Method?

// Opens a server-socket channel.
ServerSocketChannel open();// Binds the channel's socket to a local address and configures the socket to listen for connections.
ServerSocketChannel bind(SocketAddress local);// set the socket Options
ServerSocketChannel setOption(SocketOption<T> name, T value);// (import) Retrieves a server socket associated with this channel.
ServerSocket socket();/**
* (import)Accepts a connection made to this channel's socket.
*
* <p> If this channel is in non-blocking mode then this method will
* immediately return <tt>null</tt> if there are no pending connections.
* Otherwise it will block indefinitely until a new connection is available
* or an I/O error occurs.
*
* <p> The socket channel returned by this method, if any, will be in
* blocking mode regardless of the blocking mode of this channel.
*/
SocketChannel accept() throws IOException;

4. SocketChannel

1) What is SocketChannel?

A socket channel is created by invoking one of the open methods of this class.  It is not possible to create a channel for an arbitrary, pre-existing socket. A newly-created socket channel is open but not yet connected.  An attempt to invoke an I/O operation upon an unconnected channel will cause a  NotYetConnectedException to be thrown.  A socket channel can be connected by invoking its connect method; once connected, a socket channel remains connected until it is closed.  Whether or not a socket channel is connected may be determined by invoking its isConnected method.

2) What kind of feature does ServerSocketChannel support?

Socket channels support 'non-blocking connection':A socket channel may be created and the process of establishing the link to the remote socket may be initiated via the connect method for later completion by the finishConnect method. Whether or not a connection operation is in progress may be determined by invoking the isConnectionPending method.

Socket channels support 'asynchronous shutdown', which is similar to the asynchronous close operation specified in the Channel class. If the input side of a socket is shut down by one thread while another thread is blocked in a read operation on the socket's channel, then the read operation in the blocked thread will complete without reading any bytes and will return '-1'.  If the output side of a socket is shut down by one thread while another thread is blocked in a write operation on the socket's channel, then the blocked thread will receive an 'AsynchronousCloseException'.

3) How to operate it?

1. Socket options are configured using the 'setOption(SocketOption,Object)' method. Socket channels support the following options:

1 java.net.StandardSocketOptions.SO_SNDBUF (The size of the socket send buffer)

2 java.net.StandardSocketOptions.SO_RCVBUF (The size of the socket receive buffer)

3 java.net.StandardSocketOptions.SO_KEEPALIVE (Keep connection alive)

4 java.net.StandardSocketOptions.SO_REUSEADDR (Re-use address)

5 java.net.StandardSocketOptions.SO_LINGER (Linger on close if data is present (when configured in blocking modeonly))

6 java.net.StandardSocketOptions.TCP_NODELAY (Disable the Nagle algorithm)

2. Two ways to create SocketChannel

1) Open the SocketChannel and then connect to server.

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

2) Created by ServerSocketChannel when receive a new connect.

SocketChannel socketChannel = serverSocketChannel.accept();

3. Read from SocketChannel

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

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

4) What are the core method of SocketChannel?

/*** Opens a socket channel.*/
public static SocketChannel open() throws IOException/*** Connects this channel's socket.** <p> If this channel is in non-blocking mode then an invocation of this* method initiates a non-blocking connection operation.  If the connection* is established immediately, as can happen with a local connection, then* this method returns <tt>true</tt>.  Otherwise this method returns* <tt>false</tt> and the connection operation must later be completed by* invoking the {@link #finishConnect finishConnect} method.** <p> If this channel is in blocking mode then an invocation of this* method will block until the connection is established or an I/O error* occurs.*/
boolean connect(SocketAddress remote);/*** read data from channel to bytebuffer*/
int read(ByteBuffer dst);/*** write data from buffer to channel*/
int write(ByteBuffer src);

5. ServerSocket

1 What is ServerSocket?

A server socket waits for requests to come in over the network. It performs some operation based on that request, and then possibly returns a result to the requester.

2 What are the core method?

/**Binds the {@code ServerSocket} to a specific address* (IP address and port number).* <p>* If the address is {@code null}, then the system will pick up* an ephemeral port and a valid local address to bind the socket.*/void bind(SocketAddress endpoint);/*** Listens for a connection to be made to this socket and accepts* it. The method blocks until a connection is made.** <p>A new Socket {@code s} is created and, if there* is a security manager,* the security manager's {@code checkAccept} method is called* with {@code s.getInetAddress().getHostAddress()} and* {@code s.getPort()}* as its arguments to ensure the operation is allowed.* This could result in a SecurityException.*/Socket accept()

Part 3. Demo

1. FileChannel

public class FileChannelTest {public static void main(String[] args) throws Exception {// 从文件中读取FileInputStream stream = new FileInputStream("NioTest.txt");FileChannel channel = stream.getChannel();ByteBuffer buffer = ByteBuffer.allocate(10);channel.read(buffer);// 输入、输出 转换buffer.flip();while (buffer.hasRemaining()) {byte b = buffer.get();System.out.println("Character:" + (char)b);}stream.close();}}
public class FileChannelTest1{public static void main(String[] args) throws Exception {FileOutputStream stream = new FileOutputStream("NioTest1.txt");FileChannel channel = stream.getChannel();ByteBuffer buffer = ByteBuffer.allocate(512);byte[] bytes = "hello world!".getBytes();// 读到bufferfor (int i = 0; i < bytes.length; ++i) {buffer.put(bytes[i]);}// 输入、输出 转换buffer.flip();// 输出到 txtchannel.write(buffer);stream.close();}
}
public class FileChannelTest3 {public static void main(String[] args) throws Exception{FileInputStream inputStream = new FileInputStream("NioTest2.txt");FileOutputStream outputStream = new FileOutputStream("NioTest3.txt");FileChannel inputChannel = inputStream.getChannel();FileChannel outputChannel = outputStream.getChannel();ByteBuffer buffer = ByteBuffer.allocate(512);while (true) {buffer.clear();int read = inputChannel.read(buffer);System.out.println(read);if (-1 == read) {break;}buffer.flip();outputChannel.write(buffer);}inputStream.close();outputStream.close();}}

2. ServerSocketChannel

public class ScatterGatherTest {/*** Scattering 与 Gathering 的应用** <p>* telnet 或 nc 测试* </p>** @param args*/public static void main(String[] args) throws Exception{// nio 监听端口ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();InetSocketAddress address = new InetSocketAddress(8899);serverSocketChannel.socket().bind(address);// 定义消息长度9,分散给3个bufferint mesLength = 2 + 3 + 4;ByteBuffer[] buffers = new ByteBuffer[3];buffers[0] = ByteBuffer.allocate(2);buffers[1] = ByteBuffer.allocate(3);buffers[2] = ByteBuffer.allocate(4);SocketChannel socketChannel = serverSocketChannel.accept();while (true) {//读 bufferint bytesRead = 0;//读不够9个字节时,不执行后续流程while (bytesRead < mesLength) {long r = socketChannel.read(buffers);bytesRead += r;Arrays.asList(buffers).stream().map((buffer) ->  "position:" + buffer.position() + ", limit:" + buffer.limit()).forEach(System.out::println);}//读写转换Arrays.asList(buffers).forEach(buffer -> { buffer.flip(); });//写 bufferlong bytesWritten = 0;while (bytesWritten < mesLength) {long r =socketChannel.write(buffers);bytesWritten += r;}//buffer归位Arrays.asList(buffers).forEach(buffer -> buffer.clear());System.out.println("bytesRead:" + bytesRead + ", bytesWrite:" + bytesWritten + ",messageLength " + mesLength);}}
}
public class NioServer {private static HashMap<String, SocketChannel> clientMap = new HashMap<>();/*** Server端** 两次register,一次serverSocketChannel.register(),一次socketChannel.register(); 对应selectionKey.channel()强转类型不同。* * @param args*/public static void main(String[] args) throws Exception{//开启serverSocketChannel,设置非阻塞,绑定8899端口ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false);ServerSocket socket  = serverSocketChannel.socket();socket.bind(new InetSocketAddress(8899));//开启选择器,注册accept事件Selector selector = Selector.open();serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {try {int num = selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();selectionKeys.forEach(selectionKey -> {final SocketChannel client;try {// 接受新建立的连接if (selectionKey.isAcceptable()) {ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel();client = server.accept();client.configureBlocking(false);//第一次连接成功后,注册 read事件client.register(selector, SelectionKey.OP_READ);String key = "【" + UUID.randomUUID().toString() + "】";clientMap.put(key, client);} // 读取client内容else if (selectionKey.isReadable()) {client = (SocketChannel) selectionKey.channel();//定义buffer,读取channel数据ByteBuffer readBuffer = ByteBuffer.allocate(1024);int count = client.read(readBuffer);if (count > 0) {//读写翻转readBuffer.flip();Charset charset = Charset.forName("utf-8");String receiveMsg = String.valueOf(charset.decode(readBuffer).array());System.out.println(client + ":" + receiveMsg);String sendKey = null;for (Map.Entry<String, SocketChannel> entry : clientMap.entrySet()) {if (client == entry.getValue()) {sendKey = entry.getKey();break;}}//向cahnnel中,写出数据for (Map.Entry<String, SocketChannel> entry : clientMap.entrySet()) {SocketChannel value = entry.getValue();ByteBuffer writeBuffer = ByteBuffer.allocate(1024);writeBuffer.put((sendKey + ":" + receiveMsg).getBytes());writeBuffer.flip();value.write(writeBuffer);}}}selectionKeys.clear();} catch (Exception e) {e.printStackTrace();}});} catch (Exception e) {e.printStackTrace();}}}
}
public class NioClient {/*** Client端** @param args* @throws Exception*/public static void main(String[] args) throws Exception{try {SocketChannel socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);Selector selector = Selector.open();socketChannel.register(selector, SelectionKey.OP_CONNECT);socketChannel.connect(new InetSocketAddress("127.0.0.1", 8899));while (true) {selector.select();Set<SelectionKey> keySets = selector.selectedKeys();for (SelectionKey selectionKey : keySets) {if (selectionKey.isConnectable()) {SocketChannel client = (SocketChannel) selectionKey.channel();if (client.isConnectionPending()) {client.finishConnect();ByteBuffer byteBuffer = ByteBuffer.allocate(1024);byteBuffer.put((LocalDateTime.now() + "连接成功").getBytes());byteBuffer.flip();client.write(byteBuffer);ExecutorService executorService = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());executorService.submit(() -> {while (true) {try {byteBuffer.clear();InputStreamReader input = new InputStreamReader(System.in);BufferedReader br = new BufferedReader(input);String sendMessage = br.readLine();byteBuffer.put(sendMessage.getBytes());byteBuffer.flip();client.write(byteBuffer);} catch (Exception e) {e.printStackTrace();}}});}}}}} catch (Exception e) {e.printStackTrace();}}
}

【NIO】解读 java.nio.channels.Channel相关推荐

  1. 还不了解NIO ?Java NIO 核心组件详解看一下

    背景知识 同步.异步.阻塞.非阻塞 首先,这几个概念非常容易搞混淆,但NIO中又有涉及,所以总结一下[1]. 同步:API调用返回时调用者就知道操作的结果如何了(实际读取/写入了多少字节). 异步:相 ...

  2. 【NIO】解读 java.nio.channels.Selector

    目录 Part 1. What's Selector? Part 2. Why Selector? Part 3. How to use Selector? 1) Create Selector 2) ...

  3. 【IO/NIO】Java NIO浅析

    NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接 ...

  4. java nio nio2 区别_Java NIO2:NIO概述

    一.概述 从JDK1.4开始,Java提供了一系列改进的输入/输出处理的新特性,被统称为NIO(即New I/O).新增了许多用于处理输入输出的类,这些类都被放在java.nio包及子包下,并且对原j ...

  5. Java NIO系列教程(一) Java NIO 概述

    一.阻塞IO与非阻塞IO 阻塞IO: 通常在进行同步I/O操作时,如果读取数据,代码会阻塞直至有 可供读取的数据.同样,写入调用将会阻塞直至数据能够写入.传统的Server/Client模式会基于TP ...

  6. Java NIO理解与使用

    2019独角兽企业重金招聘Python工程师标准>>> Netty的使用或许我们看着官网user guide还是很容易入门的.因为Java nio使用非常的繁琐,netty对Java ...

  7. Java NIO系列教程(五)Buffer

    Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的.交互图如下: 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被 ...

  8. Java NIO 系列教程 转

    Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(B ...

  9. Java NIO 系列教程

    Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API.本系列教程将有助于你学习和理解Java NIO. Java NIO提供了与 ...

  10. 攻破JAVA NIO技术壁垒

    原文出处: 朱小厮 现在使用NIO的场景越来越多,很多网上的技术框架或多或少的使用NIO技术,譬如Tomcat,Jetty.学习和掌握NIO技术已经不是一个JAVA攻城狮的加分技能,而是一个必备技能. ...

最新文章

  1. Hadoop学习之HDFS架构(一)
  2. Windows7下Caffe的应用---在Win7下使用VS2015、Camke、Anaconda3配置Caffe CPU版本
  3. 机器学习08机器学习系统设计
  4. PRML(2)--绪论(下)模型选择、纬度灾难、决策论、信息论
  5. php自动关闭页面代码,HTML_下载完成后页面不自动关闭的方法,下载完成后页面不自动关闭的 - phpStudy...
  6. Linux性能分析之网络篇
  7. 结巴分词关键词相似度_jieba+gensim 实现相似度
  8. 面部识别实例:眼球替换
  9. java ssm 分页_ssm实现分页查询的实例
  10. 通用线程 -- sed 实例
  11. 返回json格式的编写(Msg)
  12. vscode settings.json配置
  13. 0ffice2003安装2007兼容包不能使用的解法
  14. 信道估计---LS、MMSE、LMMSE准则
  15. 搞懂:1.数据流图UML2.单代号网络图绘制3.双代号网络图绘制、工作计算法、关键路径法(含例题)
  16. 软件工程——数据流图(DFD)
  17. Nginx 负载均衡和动静分离
  18. 如何在visio中画出矩阵
  19. 中职计算机专业英语说课稿,中职英语说课稿范文
  20. Dilated Convolutions——扩张卷积

热门文章

  1. 实验四 201421440038 徐凤娇
  2. 30秒一键清理你电脑中的垃圾
  3. 交换机端口mtu值最大_mtu出现网络故障案例
  4. 南京大学计算机专业复试面试,2014 CS复试全面回忆 上机真题 面试血泪史
  5. 为什么称冯诺依曼为电子计算机之父,为什么说冯诺依曼是现代电子计算机之父...
  6. 如何批量在图片上加文字?
  7. 【python】给excel加密
  8. Wasserstein距离
  9. 中证500-小盘股预警2015.4.2
  10. 在线 excel 产品技术调研