首页 > 代码库 > Java NIO实现非阻塞式socket通信

Java NIO实现非阻塞式socket通信

博主知识水平有限,只能提供一个个人的狭隘的理解,如果有新人读到这儿,建议看一下其他教程或者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类型:

  1. SelectionKey.OP_CONNECT
  2. SelectionKey.OP_ACCEPT
  3. SelectionKey.OP_READ
  4. 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掉。

Java NIO实现非阻塞式socket通信