Java NIO series of articles
- The underlying principles of high concurrency IO and four main IO models
- Four attributes and important methods of Buffer
- The Channel tunnel class
- The Selector Selector
As you know, at a broad level, a channel can represent an underlying file descriptor, such as a hardware device, a file, a network connection, etc. However, there is more to Java NIO than that. In addition to mapping to the underlying file descriptor, Java NIO channels can be much more detailed. For example, there are different implementations of NIO Channels in Java for different network transport protocol types (TCP&UDP).
The main types of channels
FileChannel
File channel, used for reading and writing filesSocketChannel
Socket channel, used to read and write data over Socket TCP connectionsServerSocketChannel
The server socket channel (or server listening channel), which allows us to listen for TCP connection requests, creates one for each listened requestSocketChannel
Socket channel.DatagramChannel
A datagram channel for reading and writing data over UDP.
The four channels cover file IO, TCP NETWORK IO, and UDP network IO. The following is a brief introduction to the four channels from the four important operations: get, read, write and close Channel.
FileChannel FileChannel
A FileChannel is a channel dedicated to manipulating files. FileChannel allows you to either read data from a file or write data to a file. Note that FileChannel is blocking mode and cannot be set to non-blocking mode.
Get, read, write, and close a FileChannel
Through a file copy (A.txt -> b.txt) example to introduceFileChannel
Get, read, write, close
public static void copyFile(a) throws IOException {
String srcPath = ClassLoader.getSystemResource("").getPath() + "a.txt";
String destPath = ClassLoader.getSystemResource("").getPath() + "b.txt";
FileInputStream fis = new FileInputStream(srcPath);
FileOutputStream fos = new FileOutputStream(destPath);
// 1 Obtain the FileChannel channel
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
// 2 Reads data from the channel into the byteBuffer buffer
while(inChannel.read(byteBuffer) ! = -1) {
// Switch to read mode
byteBuffer.flip();
// 3 Reads data from byteBuffer and writes it to FileChannel
while(outChannel.write(byteBuffer) ! =0) {}// Clear the buffer and switch to write mode
byteBuffer.clear();
}
// 4 Forcibly flushes data to hard disks
outChannel.force(true);
// 5 Close the channel
inChannel.close();
outChannel.close();
}
Copy the code
SocketChannel SocketChannel
In NIO, there are two channels that involve network connectivity
SocketChannel
Responsible for connection transmissionServerSocketChannel
Responsible for connection monitoring
Both ServerSocketChannel and SocketChannel support blocking and non-blocking modes. How do you set the mode? Call the configureBlocking method as follows:
SocketChannel. ConfigureBlocking (false)
Set to non-blocking mode.SocketChannel. ConfigureBlocking (true)
Set to blocking mode.
In blocking mode, SocketChannel’s connect, read, and write operations are synchronous and blocking, as efficient as the flow-oriented blocking read and write operations of Java’s older IO.
The following describes how to get, read, write, and close a SocketChannel by sending a message from a client to a server
The client
public class SocketChannelClient {
private static final String HOSTNAME = "127.0.0.1";
private static final int PORT = 8890;
private static final SocketAddress socketAddress = new InetSocketAddress(HOSTNAME, PORT);
public static void main(String[] args) throws IOException {
client();
}
private static void client(a) throws IOException {
// Get the socket transport channel
SocketChannel socketChannel = SocketChannel.open(socketAddress);
// Set it to non-blocking
socketChannel.configureBlocking(false);
while(! socketChannel.finishConnect()) {// If the connection is not blocked, connect will immediately return the result of the client connecting to the server
// So you need to constantly spin to check if you are currently connected to the server
}
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byteBuffer.put("hello world".getBytes());
// ByteBuffer is read before writing
byteBuffer.flip();
socketChannel.write(byteBuffer);
// Terminates the output method by sending an end flag to the other end of the output
socketChannel.shutdownOutput();
// Close the socket connectionsocketChannel.close(); }}Copy the code
The service side
public class SocketChannelServer {
private static final String HOSTNAME = "127.0.0.1";
private static final int PORT = 8890;
private static final SocketAddress socketAddress = new InetSocketAddress(HOSTNAME, PORT);
public static void main(String[] args) throws IOException {
server();
}
private static void server(a) throws IOException {
// Get the server socket
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// Change to non-blocking mode
serverSocketChannel.configureBlocking(false);
/ / binding IP + port
serverSocketChannel.bind(socketAddress);
// Spin to wait for client connection
SocketChannel socketChannel = null;
while ((socketChannel = serverSocketChannel.accept()) == null) {
}
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
// Read data from socketChannel and write to byteBuffer
while(socketChannel.read(byteBuffer) ! = -1) {
// Switch to read mode
byteBuffer.flip();
System.out.println(new String(byteBuffer.array()));
// The situation buffer is switched to write mode
byteBuffer.clear();
}
// Close the socketsocketChannel.close(); serverSocketChannel.close(); }}Copy the code