当前位置:网站首页>Detailed explanation of NiO channel
Detailed explanation of NiO channel
2022-07-21 20:14:00 【Ordinary people zzz~】
FileChannel
One 、 passageway (channel) Introduce
Channel It's an object , It is used to connect the source node and the target node , stay java NIO Is responsible for the transfer of buffer data .Channel It doesn't store data on its own , So we need to cooperate with buffer to transmit .
Two 、 Primary implementation class
The main implementation classes are as follows : FileChannel, SocketChannel, ServerSocketChannel, DatagramChannel
,
3、 ... and 、 Get access to
- Java Provided for classes that support channels getChannel() Method
Local IO | The Internet IO |
---|---|
FileInputStream/FileOutputStream | Socket |
RandomAccessFile | ServerSocket |
nothing | DatagramSocket |
- stay JDK1.7 Medium NIO.2 Static methods are provided for each channel open()
- stay JDK1.7 Medium NIO.2 Of Files The utility class newByteChannel()
public static void main(String[] args) throws Exception {
// 1 Local IO Get access to
FileInputStream inputStream = new FileInputStream(resourceFilePath);
FileOutputStream outputStream = new FileOutputStream(targetFilePath);
FileChannel inChannel = inputStream.getChannel();
FileChannel outChannel = outputStream.getChannel();
// 2. adopt open Method to get
FileChannel.open(Paths.get(resourceFilePath), StandardOpenOption.READ);
FileChannel.open(Paths.get(targetFilePath),
StandardOpenOption.READ,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE);
}
Four 、 Case study
4.1 FileChannel- File replication
public class FileNioTest {
public static void main(String[] args) {
String resourceFilePath = "D:\\test\\copyFileTest.txt";
String targetFilePath = "D:\\test\\copyFileTest-1.txt";
// Copy file
// copyFile1(resourceFilePath, targetFilePath);
// copyFile2(resourceFilePath, targetFilePath);
copyFile3(resourceFilePath, targetFilePath);
}
private static void copyFile1(String resourceFilePath, String targetFilePath) {
// Use FileChannel Cooperate with the buffer to realize the function of file replication
try (
FileInputStream inputStream = new FileInputStream(resourceFilePath);
FileOutputStream outputStream = new FileOutputStream(targetFilePath);
FileChannel inChannel = inputStream.getChannel();
FileChannel outChannel = outputStream.getChannel();
) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inChannel.read(buffer) != -1) {
// Toggle read mode
buffer.flip();
outChannel.write(buffer);
// Empty
buffer.clear();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void copyFile2(String resourceFilePath, String targetFilePath) {
// File copying is realized by memory mapping file
try (
FileChannel inChannel = FileChannel.open(Paths.get(resourceFilePath), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get(targetFilePath),
StandardOpenOption.READ,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE);
) {
MappedByteBuffer inMap = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMap = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
byte[] b = new byte[inMap.limit()];
// Get data from disk file and write it to b Byte array
inMap.get(b);
// take b The data in the byte array is written to the disk file
outMap.put(b);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void copyFile3(String resourceFilePath, String targetFilePath) {
// Channel-to-channel Way to achieve replication : Zero copy mode
try (
FileChannel inChannel = FileChannel.open(Paths.get(resourceFilePath), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get(targetFilePath),
StandardOpenOption.READ,
StandardOpenOption.WRITE,
StandardOpenOption.CREATE);
) {
// inChannel.transferTo(0, inChannel.size(), outChannel);
outChannel.transferFrom(inChannel, 0, inChannel.size());
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.2 SocketChannel、ServerSocketChannel
Case study : adopt NIO Realize multi person chat room
4.1 Server side Server
public class Server {
public void start() throws IOException {
// establish selector
Selector selector = Selector.open();
// establish ServerSocketChannel, And bind the listening port
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(9999));
// take Channel Set to non-blocking mode
serverSocketChannel.configureBlocking(false);
// take Channel Sign up to Selector On , Listen for connection Events
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("------------- Server started successfully ---------------");
while (true) {
// Cycle call Selector Of select Method , Test Readiness
int i = selector.select();
if (i == 0) {
continue;
}
// call selectedKeys Method to get ready channel aggregate
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
iterator.remove();
// Determine the type of ready event , Call the business processing method
if (selectionKey.isAcceptable()) {
acceptable(serverSocketChannel, selector);
} else if (selectionKey.isWritable()) {
System.out.println("----------Writable");
} else if (selectionKey.isReadable()) {
readable(selectionKey, selector);
} else if (selectionKey.isConnectable()) {
System.out.println("----------Connectable");
}
}
}
}
/** * Readable event handling methods * * @param selectionKey * @param selector * @throws IOException */
private void readable(SelectionKey selectionKey, Selector selector) throws IOException {
// from selectionKey Get the ready channel
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
// establish byteBuffer
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
StringBuffer sb = new StringBuffer();
// Get the message of the client
while (socketChannel.read(byteBuffer) > 0) {
byteBuffer.flip();
sb.append(Charset.forName("utf-8").decode(byteBuffer));
byteBuffer.clear();
}
System.out.println(sb.toString());
// take channel Register again to selector On , Listen for its readable events
socketChannel.register(selector, SelectionKey.OP_READ);
if (sb.toString().length() != 0) {
// Broadcast to other clients
broadCast(selector, socketChannel, sb.toString());
}
}
/** * Handle connection Events * * @param serverSocketChannel * @param selector * @throws IOException */
private void acceptable(ServerSocketChannel serverSocketChannel, Selector selector) throws IOException {
// Get to connect
SocketChannel socketChannel = serverSocketChannel.accept();
// take Channel Set to non-blocking mode
socketChannel.configureBlocking(false);
// take Channel Sign up to Selector On , Listen for connection Events
socketChannel.register(selector, SelectionKey.OP_READ);
// Return message to client
socketChannel.write(Charset.forName("utf-8").encode(" Connection established successfully !"));
}
/** * Broadcast to other clients * * @param selector * @param socketChannel Current client object * @param sb news */
private void broadCast(Selector selector, SocketChannel socketChannel, String sb) {
// Get all connections SelectionKey
Set<SelectionKey> keys = selector.keys();
keys.forEach(key -> {
Channel channel = key.channel();
// Remove the current client
if (channel instanceof SocketChannel && channel != socketChannel) {
try {
// Send a message
((SocketChannel) channel).write(Charset.forName("utf-8").encode(sb));
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public static void main(String[] args) throws IOException {
new Server().start();
}
}
4.2 client Client
public class ClientA {
private String name;
public ClientA(String name) {
this.name = name;
}
public void start() throws IOException {
// Connect to server
SocketChannel socketChannel = SocketChannel.open(
new InetSocketAddress("127.0.0.1", 9999)
);
// Receive the server response message
Selector selector = Selector.open();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
ClientThread thread = new ClientThread();
thread.setSelector(selector);
new Thread(thread).start();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String sb = scanner.nextLine();
socketChannel.write(Charset.forName("utf-8").encode(this.name + ":" + sb.trim()));
}
}
public static void main(String[] args) throws IOException {
new ClientA(" Ordinary people ").start();
}
}
ClientThread
public class ClientThread implements Runnable {
private Selector selector;
public void setSelector(Selector selector) {
this.selector = selector;
}
@Override
public void run() {
try {
while (true){
int i = selector.select();
if (i == 0){
continue;
}
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
iterator.remove();
if (selectionKey.isReadable()){
readable(selectionKey);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/** * Readable event handling methods * @param selectionKey * @throws IOException */
private void readable(SelectionKey selectionKey) throws IOException {
// from selectionKey Get the ready channel
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
// establish byteBuffer
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
StringBuffer sb = new StringBuffer();
// Get the message of the client
while (socketChannel.read(byteBuffer) > 0){
byteBuffer.flip();
sb.append(Charset.forName("utf-8").decode(byteBuffer));
}
// take channel Register again to selector On , Listen for its readable events
socketChannel.register(selector, SelectionKey.OP_READ);
System.out.println(sb.toString());
}
}
4.3 DatagramChannel
SocketChannel Created is TCP Connect ,DatagramChannel Then you create UDP Connect .
establish DatagramChannel And create others socket The channels are the same : Call static open( )
Method to create a new instance . new DatagramChannel There will be one that can be called socket( )
Method DatagramSocket object .DatagramChannel Objects can act as servers ( monitor ) It can also act as a client ( sender ).
DatagramChannel channel = DatagramChannel.open( );
DatagramSocket socket = channel.socket( );
socket.bind (new InetSocketAddress (9999));
DatagramChannel It's disconnected . Every datagram (datagram) It's all a self-contained entity , It has its own destination address and does not rely on the data payload of other datagrams . And flow oriented socket Different ,DatagramChannel You can send separate datagrams to different destinations . Again ,DatagramChannel Object can also receive packets from any address . Each incoming datagram contains information about where it came from ( source address SocketAddress).
// open DatagramChannel
DatagramChannel channel = DatagramChannel.open();
InetSocketAddress sendAddress = new InetSocketAddress(9999);
// binding
channel.bind(sendAddress);
ByteBuffer buffer = ByteBuffer.allocate(1024);
// receive
while (true) {
buffer.clear();
SocketAddress socketAddress = channel.receive(buffer);
buffer.flip();
System.out.println(Charset.forName("UTF-8").decode(buffer));
}
1. open DatagramChannel
adopt 9999 Port to receive UDP Message data
DatagramChannel server = DatagramChannel.open();
server.socket().bind(new InetSocketAddress(9999));
2. receive data
adopt DatagramChannel.receive()
receive UDP Message data
public static void testReceive() throws IOException {
// open DatagramChannel
DatagramChannel receiveChannel = DatagramChannel.open();
InetSocketAddress sendAddress = new InetSocketAddress(9999);
// binding
receiveChannel.bind(sendAddress);
ByteBuffer buffer = ByteBuffer.allocate(1024);
// receive
while (true) {
buffer.clear();
SocketAddress socketAddress = receiveChannel.receive(buffer);
buffer.flip();
System.out.println(Charset.forName("UTF-8").decode(buffer));
}
}
3. send data
adopt DatagramChannel.send()
send out UDP Message data
public static void testSend() throws IOException {
// open DatagramChannel
DatagramChannel sendChannel = DatagramChannel.open();
InetSocketAddress sendAddress = new InetSocketAddress("127.0.0.1", 9999);
// send out
ByteBuffer buffer = ByteBuffer.wrap(String.format("client send:%s", System.currentTimeMillis()).getBytes(StandardCharsets.UTF_8));
sendChannel.send(buffer, sendAddress);
System.out.println("send success");
}
4. Connect
UDP There is no real connection , The connection here is to a specific service address read() / write()
receive / send out Data packets
public static void testConnect() throws IOException {
// open DatagramChannel
DatagramChannel connChannel = DatagramChannel.open();
// binding
connChannel.bind(new InetSocketAddress(9999));
// Connect
connChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
// write Method
connChannel.write(ByteBuffer.wrap(String.format("test connect:%s", System.currentTimeMillis()).getBytes(StandardCharsets.UTF_8)));
// buffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
buffer.clear();
connChannel.read(buffer);
buffer.flip();
System.out.println(Charset.forName("UTF-8").decode(buffer));
}
}
Be careful :read()
and write()
Only in connect()
Only after that can we use , Or you'll throw NotYetConnectedException
abnormal , use read()
Reception time , If no packets are received , Flip a PortUnreachableException
abnormal .
Reference resources :https://blog.csdn.net/qq_38526573/article/details/89207100
边栏推荐
- 微信公众号开发接入,利用微信公众平台申请测试号进行本地开发
- How do I optimize from 20s to 500ms
- 自动抓包工具 web scraper
- MySQL之DCL(数据控制语言)
- JFrame需要调整大小才可以显示控件 在JPanel中setBounds()方法不起作用
- 高德地图API获取当前位置对应的周边信息
- Character function and memory function
- Chart is code: build a new generation of graphics library in a coded way -- feekin
- From March to June, after summary, more than 200 pages of true question notes and detailed explanations (including core test sites and 6 major factories)
- UML模型和类的六大关系
猜你喜欢
Jenkins插件开发——提供对外访问接口
@Scheduled 定时任务详解
以独占的方式锁定此配置文件失败。另一个正在运行的VMware进程可能正在使用配置文件。
Linux Redis-6.2.6单机部署
Nacos-配置中心原理解析
拉取项目pom文件报错,jai_core-1.1.3.jar,解决jar引入问题
fastJson数据类型中,解析JSONObject出现$ref: “$.list[0]“问题
As editor sets the indent position of the code on the right side of fluent development
3-6月面经总结,200多页真题笔记和详解(含核心考点及6家大厂)
Fluent customizes form and encapsulates form components
随机推荐
Analyse du principe du Centre de configuration nacos
数据类型Map判空 、空字符串、空key值等各种判断方法,全网最详细
快捷键、命令
The JSON tool converts objects to JSON format strings
Pycharm创建SQLite数据库
Okaleido tiger NFT is about to log in to binance NFT platform, and the future market continues to be optimistic
Trigonometric formula of 3D mathematics
Jprofiler安装及使用教程
批量去除文件名中的空格,替换数据库中存储数据的空格
转换String三种方式比较:(String)、toString()、String.valueOf()
How to successfully get offers from ant, jd.com, Xiaomi, Tencent and other major manufacturers
MySql update语句或者delete语句 where条件没走索引会锁表
CentOS 8中Docker安装MySQL8
markdown及IDEA快捷键
注解相关学习
MySQL DML (data manipulation language)
Chart is code: build a new generation of graphics library in a coded way -- feekin
利用反汇编调试与补码解释0x80000000 / -1整形输出异常不一致
As editor sets the indent position of the code on the right side of fluent development
@Scheduled 定时任务详解