Android NIO 系列教程(一) NIO概述
Android NIO 系列教程(二) – Channel
Android NIO 系列教程(三) – Buffer
Android NIO 系列教程(四) – Selector
Android NIO 系列教程(五) – FileChannel
Android NIO 系列教程(六) – SocketChannel
Android NIO 系列教程(七) – ServerSocketChannel
Android NIO 系列教程(八) --NIO简易聊天室
这一章,我们来学习 SocketChannel。
SocketChannel 用于 Tcp 网络连接的通道,类似于非阻塞的 Socket,它可以通过以下两种方式创建:
- 通过 SocketChannel 的open()方法,并 connect 网络上的服务器
- 当 ServerSocketChannel 连接到一个请求,也会创建 SocketChannel。
创建 SocketChannel
通过 open() 方法创建:
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
关闭 SocketChannel
可以通过 close() 方法关闭:
socketChannel.close();
从 SocketChannel 读数据
可以使用 read() 方法:
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf);
首先创建一个buffer,然后通过 read() 方法,把数据从 SocketChannel 读到buffer;它的返回值表示能读取到多少个字节数,如果返回 -1 ,则表示已经读到流的末尾了。
写数据到SocketChannel
可以使用 write() 方法,参数为 buffer:
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}
注意写数据这里,用到了 while循环,因为我们不确定有多少字节会被写入。
非阻塞模式
我们可以把 SocketChannel 设置为非阻塞模式,这样当我们在调用 connect(), read() and write() 方法时,都是异步的。
如果我们设置了非阻塞模式,当我们调用 connect 方法,它可能在连接建立前就会返回,所以,我们可以使用 finishConnect() 方法判断是否完成:
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
while(! socketChannel.finishConnect() ){
//wait, or do something else...
}
write() 方法
当你设置为非阻塞模式,write() 方法调用并返回时,不一定表示你的数据已经成功写入,因此我们需要把 write() 放到 循环方法内:
while(buf.hasRemaining()) {
channel.write(buf);
}
read() 方法
当你设置为非阻塞模式,read() 方法调用并返回时,不一定数据已经读取到数据了,所以需要判断返回值的大小,它会告诉你实际读取了多少数据。
非阻塞模式和 Selector
SocketChannel 的非组设模式可以很好配合 selector ,当向 selector 注册一个或多个 SocketChannel 时,你可以通过 selector 判断哪些 channel 是可读可写的。关于这些,我们后面介绍。
下一章,我们学习 ServerSocketChannel。