JAVA NIO 之 channel通道(知识二)

简介:

java nio 通道上一篇文章里就讲述过,channel总是写数据的时候,要先把数据写入到bytebuffer,读数据的时候总是要先从channel中读入到bytebuffer。如下图,这个图是好多知名博客常用的图,很好理解这个channel。

wKioL1mPKOfiRUviAAAlAoB14ME679.png-wh_50


channel分为一下几种:

  1. FileChannel

  2. SocketChannel

  3. ServerSocketChannel

  4. DatagramChannel


FileChannel:

经常说的FileChannel都是拿下面的例子说事

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package  com.nio.basic;
 
import  java.io.IOException;
import  java.io.RandomAccessFile;
 
/**
  * Created by sdc on 2017/8/13.
  */
public  class  RandomAccessFileTest {
 
     public  static  void  main(String[] args) {
         readFile();
     }
 
     /**
      * 读取文件
      * @throws Exception
      */
     public  static  void  readFile(){
         String fileName =  "C:\\Users\\sdc\\Desktop\\gc (2).log" ;
         RandomAccessFile randomAccessFile =  null ;
         try {
             randomAccessFile =  new  RandomAccessFile(fileName,  "r" );
             long  fileLength = randomAccessFile.length();
             System.out.print( "length"  + fileLength);
 
             int  start =  100 ;
             randomAccessFile.seek(start);
             byte [] bytes =  new  byte [ 20 ];
             int  read =  0 ;
             while  ((read = randomAccessFile.read(bytes)) != - 1 ) {
                 System.out.println( new  String(bytes,  "UTF-8" ));
             }
 
             System.out.println(bytes.length);
             System.out.println( new  String(bytes,  "UTF-8" ));
 
         } catch  (Exception e) {
             e.printStackTrace();
         } finally  {
             if  (randomAccessFile !=  null ) {
                 try  {
                     randomAccessFile.close();
                 catch  (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
     }
 
}


还有这样的例子:

1
2
FileInputStream is =  new  FileInputStream( new  File(src));
FileChannel channelFrom = is.getChannel();

其实这两个是用到了nio的channel,不妨自己写一个例子试试。


SocketChannel和ServerSocketChannel一般是两个集合起来说的,一个用于客户端连接,一个用于服务端连接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package  com.nio.basic;
 
import  java.io.IOException;
import  java.net.InetSocketAddress;
import  java.nio.ByteBuffer;
import  java.nio.channels.SelectionKey;
import  java.nio.channels.Selector;
import  java.nio.channels.ServerSocketChannel;
import  java.nio.channels.SocketChannel;
import  java.util.Iterator;
import  java.util.Set;
 
/**
  * nio 服务端
  * Created by sdc on 2017/8/13.
  */
public  class  NIoServer {
 
     ByteBuffer buffer = ByteBuffer.allocate( 1024 );
 
     public  static  void  main(String[] args)  throws  IOException {
         System.out.println( "server started..." );
         try  {
             new  NIoServer().run();
         catch  (Exception e) {
             e.printStackTrace();
         }
     }
 
     public  void  run ()  throws   Exception {
         //打开服务器端的套接字通道
         ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
         //服务器端设置为非阻塞
         serverSocketChannel.configureBlocking( false );
         //服务端进行绑定
         serverSocketChannel.bind( new  InetSocketAddress( "localhost" 8000 ));
 
         //注册感兴趣的事件
         Selector selector = Selector.open();
         serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
 
         while  ( true ) {
             int  selectCount = selector.select();
             if ( selectCount == 0  ) {
                 continue ;
             }
 
             selector.select();
             Set<SelectionKey> keys = selector.selectedKeys();
             //获取迭代器
             Iterator<SelectionKey> keyIterator = keys.iterator();
 
             while  (keyIterator.hasNext()) {
                 SelectionKey key = keyIterator.next();
                 if  (!key.isValid()) {
                     continue ;
                 }
                 if  (key.isAcceptable()) {
                     ServerSocketChannel  sscTemp = (ServerSocketChannel) key.channel();
                     //得到一个连接好的SocketChannel,并把它注册到Selector上,兴趣操作为READ
                     SocketChannel socketChannel = sscTemp.accept();
                     socketChannel.configureBlocking( false );
                     socketChannel.register(selector, SelectionKey.OP_READ);
                     System.out.println( "REGISTER CHANNEL , CHANNEL NUMBER IS:"  + selector.keys().size());
                 else  if  (key.isReadable()) {
                     //读取通道中的数据
                     SocketChannel channel = (SocketChannel) key.channel();
                     read(channel);
                 }
                 keyIterator.remove();  //该事件已经处理,可以丢弃
             }
         }
     }
 
     private  void  read(SocketChannel channel)  throws  IOException {
         int  count ;
         buffer.clear();
         try  {
             while  ((count = channel.read(buffer)) >  0 ) {
                 buffer.flip();
                 byte [] bytes =  new  byte [buffer.remaining()];
                 buffer.get(bytes);
                 System.out.println( "READ FROM CLIENT:"  new  String(bytes));
             }
             if  (count <  0 ) {
                 channel.close();
             }
         catch  (IOException e) {
             e.printStackTrace();
         }
     }
 
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package  com.nio.basic;
 
import  java.io.IOException;
import  java.net.InetSocketAddress;
import  java.nio.ByteBuffer;
import  java.nio.channels.SocketChannel;
import  java.util.Random;
import  java.util.concurrent.ExecutorService;
import  java.util.concurrent.Executors;
import  java.util.concurrent.TimeUnit;
 
/**
  * nio 客户端
  * Created by sdc on 2017/8/13.
  */
public  class  NioClient {
 
     public  static  void  main(String[] args) {
         ExecutorService executorService = Executors.newCachedThreadPool();
         executorService.submit( new  Client( "nio-client-1" ));
         executorService.submit( new  Client( "nio-client-2" ));
         executorService.submit( new  Client( "nio-client-3" ));
         executorService.shutdown();
     }
 
     static  class  Client  extends  Thread {
 
         private  String clientThreadName;
 
         ByteBuffer buffer = ByteBuffer.allocate( 1024 );
 
         Random random =  new  Random( 20 );
 
         Client(String clientThreadName) {
             this .clientThreadName = clientThreadName;
         }
 
         @Override
         public  void  run() {
             SocketChannel channel =  null ;
             try  {
                 channel = SocketChannel.open();
                 channel.configureBlocking( false );
                 channel.connect( new  InetSocketAddress( "localhost" 8000 ));
                 while  (!channel.finishConnect()) {
                     TimeUnit.MICROSECONDS.sleep( 100 );
                 }
 
                 for  ( int  i= 0 ; i< 5 ; i++) {
                     TimeUnit.MICROSECONDS.sleep( 100  * random.nextInt());
                     String message =  "send message "  + i +  " from"  + clientThreadName;
                     buffer.put(message.getBytes());
                     buffer.flip();
 
                     //buffer先把数据读入到buffer,然后channel先把buffer中的数据写入到channel,
                     channel.write(buffer);
 
                     buffer.clear();
                 }
 
             catch  (IOException e) {
                 e.printStackTrace();
             catch  (InterruptedException e) {
                 e.printStackTrace();
             } finally  {
                 try  {
                     channel.close();
                 catch  (IOException e) {
                     e.printStackTrace();
                 }
             }
 
         }
 
     }
 
 
}


JAVA NIO Selector 知识三 http://shangdc.blog.51cto.com/10093778/1956602


JAVA NIO buffer (知识三)

http://shangdc.blog.51cto.com/10093778/1956602


JAVA NIO 之 channel通道(知识二)


http://shangdc.blog.51cto.com/10093778/1955874


JAVA NIO 知识一

http://shangdc.blog.51cto.com/10093778/1955793



本文转自 豆芽菜橙 51CTO博客,原文链接:http://blog.51cto.com/shangdc/1955874

相关文章
|
2月前
|
存储 Java 数据处理
|
2月前
|
Java API
java中IO与NIO有什么不同
java中IO与NIO有什么不同
|
8天前
|
网络协议 Java Linux
Java基础BIO、NIO、AIO小结(下)
Java基础BIO、NIO、AIO小结(下)
16 0
|
8天前
|
缓存 Java 测试技术
Java基础BIO、NIO、AIO小结(上)
Java基础BIO、NIO、AIO小结
17 0
|
11天前
|
缓存 Java API
Java NIO和IO之间的区别
NIO(New IO),这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。
14 1
|
16天前
|
监控 Java 开发者
深入理解 Java 网络编程和 NIO
【4月更文挑战第19天】Java网络编程基于Socket,但NIO(非阻塞I/O)提升了效率和性能。NIO特点是非阻塞模式、选择器机制和缓冲区,适合高并发场景。使用NIO涉及通道、选择器和事件处理,优点是高并发、资源利用率和可扩展性,但复杂度、错误处理和性能调优是挑战。开发者应根据需求选择是否使用NIO,并深入理解其原理。
|
18天前
|
存储 监控 Java
浅谈Java NIO
浅谈Java NIO
6 0
|
18天前
|
消息中间件 存储 Java
【Java NIO】那NIO为什么速度快?
是这样的,在NIO零拷贝出现之前,一个I/O操作会将同一份数据进行多次拷贝。可以看下图,一次I/O操作对数据进行了四次复制,同时来伴随两次内核态和用户态的上下文切换,众所周知上下文切换是很耗费性能的操作。
26 0
【Java NIO】那NIO为什么速度快?
|
21天前
|
存储 监控 Java
Java输入输出:什么是NIO(New I/O)?
Java NIO是一种高效I/O库,特征包括非阻塞性操作、通道(如文件、网络连接)、缓冲区和选择器。选择器监控通道状态变化,通知应用程序数据可读写,避免轮询,提升性能。示例代码展示了一个使用NIO的服务器,监听连接、读取数据并处理客户端通信。
14 1
|
3月前
|
移动开发 编解码 网络协议
用Java的BIO和NIO、Netty来实现HTTP服务器(三) 用Netty实现
用Java的BIO和NIO、Netty来实现HTTP服务器(三) 用Netty实现