Java NIO之通道Channel

channel与流的区别:

  • 流基于字节,且读写为单向的。
  • 通道基于快Buffer,可以异步读写。除了FileChannel之外都是双向的。

channel的主要实现:

  • FileChannel
  • DatagramChannel:UDP读写
  • SocketChannel:TCP读写
  • ServerSocketChannel

支持scatter/gather(分散和聚集)

        1. 分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中。因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中。
          聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,因此,Channel 将多个Buffer中的数据“聚集(gather)”后发送到Channel。
ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] bufferArray = { header, body };
channel.read(bufferArray);

通道的创建:

除了FileChannel之外,都使用open创建。

FileChannel的创建如下:

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();

Socket通道

分别对应java.net包中的Socket对象ServerSocket、Socket和DatagramSocket;Socket通道被实例化时,都会创建一个对等的Socket对象。

Socket通道可以运行非阻塞模式并且是可选择的,非阻塞I/O与可选择性是紧密相连的,这也正是管理阻塞的API要在 SelectableChannel中定义的原因。设置非阻塞非常简单,只要调用configureBlocking(false)方法即可。如果需要中 途更改阻塞模式,那么必须首先获得blockingLock()方法返回的对象的锁。

ServerSocketChannel实例:

1. 使用对等socket来bind监听。

2. 非阻塞状态下,accept在无连接时立即返回null

ByteBuffer buffer = ByteBuffer.wrap("Hello World".getBytes());
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(12345));
ssc.configureBlocking(false);
for (;;) {
System.out.println("Waiting for connections");
SocketChannel sc = ssc.accept();
if (sc == null)
TimeUnit.SECONDS.sleep(2000);
else {
System.out.println("Incoming connection from:" + sc.socket().getRemoteSocketAddress());
buffer.rewind();
sc.write(buffer);
sc.close();
}
}
  • SocketChannel 
           相对于ServerSocketChannel,它扮演客户端,发起到监听服务器的连接,连接成功后,开始接收数据。 
           调用它的open()方法仅仅是打开但并未连接,要建立连接需要紧接着调用connect()方法;也可以两步合为一步,调用open(SocketAddress remote)方法。 
           你会发现connect()方法并未提供timout参数,作为替代方案,你可以用isConnected()、isConnectPending()或finishConnect()方法来检查连接状态。
  • 1. isConnected判断是否已经建立
  • 2. finishConnect在非阻塞套接字上阻塞等待连接成功

非阻塞的read在无数据时立即返回0

  • DatagramChannel 
           它是无连接的,它既可以作为服务器,也可以作为客户端。
上一篇:详解 通道 (Channel 接口)


下一篇:《C++ 并发编程》- 第1章 你好,C++的并发世界