Java NIO SocketChannel 是一个连接TCP网络socket的channel。与标准库的网络Socket是等效的。有两个办法可以来建立SocketChannel
- 打开了 SocketChannel 连接到了网络上的一个服务
- 传入了 ServerSocketChannel 连接
打开 SocketChannel
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("http://tutorials.jenkov.com", 80));
关闭 SocketChannel
使用完毕后需要关闭Channel
socketChannel.close();
从SocketChannel读取数据
通过调用read()
方法来读取数据
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf);
首先,分配Buffer,数据将从SocketChannel读到Buffer。
然后,调用read()
方法,从SocketChannel读数据到Buffer。返回值来表示有多少字节的数据写入到来Buffer。如果返回-1
则表示已经写完了。
写数据到SocketChannel
通过调用write()
方法了来写入数据
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);
}
与 FileChannel
类似,write()
方法在循环内部被调用。
非阻塞模式
我们可以把SocketChannel置为非阻塞模式,然后就可以在异步调用connect()
, read()
, write()
方法
connet()
在非阻塞模式下,建立连接可以调用connect()
方法,此方法可能在连接建立前返回(因为是非阻塞的)。可以通过调用finishConnect()
方法来确认连接是否已建立。
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
while(! socketChannel.finishConnect() ){
//wait, or do something else...
}
write()
在非阻塞模式下,write()
方法可能在未写入数据前返回。因此同样在循环内调用,例子与之前的一致。
read()
在非阻塞模式下,read()
方法可能没有返回真正读取到的数据,因此需要注意其出参,也就是’读取’了多少字节的数据.
非阻塞模式下的 Selectors
非阻塞模式下的SocketChannel 与 Selectors配合的很好,注册一个或多个SocketChannel到Selector,可以向Selector查询有多少个channel是可读或可写的。