博主知识水平有限,只能提供一个个人的狭隘的理解,如果有新人读到这儿,建议看一下其他教程或者API,如果不明白,再来看一下;如果有dalao读到这儿,希望能指出理解中的问题~谢谢
Java提供了用于网络通信的socket和serversocket包,然而实现方式是阻塞式的,同一时间点上只能进行一个连接,这会带来不好的体验。当然了,我们也可以通过不断创建线程的方式管理连接,但线程多了的话反而会降低效率。于是Java推出了非阻塞式IO——channel。并且channel提供关于网络通信的相关channel。
channel将传统的输入输出流合并了,即一个channel既可以输入内容,也可以输出内容。
并且,使用channel的同时,要用NIO提供的buffer作为中介。
channel类型:
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
buffer类型:
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
为了使用socketchannel与serversocketchannel,请使用工厂模式创建byteBuffer:
ByteBuffer byteBuffer = ByteBuffer.allocate(12);
创建Channel方法:
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
下条语句将指定channel设为非阻塞式:
serverSocketChannel.configureBlocking(false);
与某端口绑定:
serverSocketChannel.bind(new InetSocketAddress(PORT));
相应的如果是socketChannel,方法是connect,这里仅拿ServerSocketChannel举例。
到此为止,我们还没有看到channel是如何实现非阻塞式IO的,于是NIO提供了一种工具——Selector。
Selector,简单来说,是对多个channel的管理工具,我们可以把多个channel一股脑加进去,如果哪个channel准备好读或者写(或者其他操作)就会通知我们。
Selector中有一个interest的概念,意思是在我们把某个通道注册给selector时,我们指明selector要监视channel的哪一种行为,毕竟,一种channel可以read,write,accept,connect。
Selector实例化:
Selector selector = Selector.open();
channel注册
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
第二个参数为interest类型
interest类型:
- SelectionKey.OP_CONNECT
- SelectionKey.OP_ACCEPT
- SelectionKey.OP_READ
- SelectionKey.OP_WRITE
一般的我们给serverSocketChannel注册一个accept就好。
然后,当我们调用selector.select()时,selector会等待已经注册的channel,直到有一个channel准备好。这个过程是阻塞式的,当然了阻塞又有什么关系呢,其实IO还是非阻塞式的。
之后我们引用selector.selectedKeys()会返回一个集合,包含了可以响应的channel,迭代集合,我们得到一个个channel。
噢,其实并不是得到channel,而是另一种东西——SelectionKey。
SelectionKey包含了挺多信息的,你可以得到他的selector,channel还有注册时的信息。
我们可以通过selectionKey.isReadable,isAcceptable,isConnectable,isWritable获得我们注册时的信息,然后具体的对每种响应类型处理。
还有,记得迭代完要把对象remove掉。