9 Java NIO SocketChannel-翻译

216 阅读2分钟

Java NIO的SocketChannel是一个连接到TCP网络的Channel。创建ScoketChannel有两种方式:

  1. 打开一个SocketChannel,并且连接到互联网上的某台服务器。
  2. 一个新连接到达ServerSocketChannel时,会创建SocketChannel。

Opening a SocketChannel

SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InnetSocketAddress("http://jenkov.com",80);

Closing a SocketChannel

关闭SocketChannel可以通过SocketChannel.close()方法。如下所示。

socketChannel.close();

Reading from a SocketChannel

可以通过read()方法来实现从SocketChannel中读取数据。下面是一个例子:

ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf);

首先,为一个Buffer分配空间,从SocketChannel中读到的数据会写入到这个Buffer中。

然后,调用SockedChannel的read()方法。这个方法会将SocketChannel中的数据写入到Buffer中。read()方法的返回值表示写入到Buffer中的字节数。如果返回-1,说明已经到达流的末尾(连接已经关闭)。

Writing to a SocketChannel

可以通过SocketChannel.write()方法向SocketChannel写入数据,这个方法将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);
}

注意SocketChannel.write()方法的调用是在一个while循环中的。Write()方法无法保证能写多少字节到SocketChannel。所以,我们重复调用write()直到Buffer没有要写的字节为止。

Non-blocking Mode

可以将SocketChannel设置为非阻塞模式。这样做以后,connect(),read()和write()方法都将工作在异步模式。

connect()

如果SocketChannel工作在非阻塞模式,那么可以调用connect()方法,这个方法可能会在连接建立之前就返回。为了判断连接是否已经建立了,可以通过调用finishConnect()方法,如下所示:

socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("http://jenkov.com",80);

while(! socketChannel.finishConnect()){
    // wait,or do something else ...
}

write()

在非阻塞模式中,write()方法会在没有写任何数据之前就返回。因此,需要在循环中调用write()方法。但是,由于这个已经在前面的例子中讲过了,这里也没有什么需要进行特殊处理。

read()

在非阻塞模式中, read()方法会在没有读到任何数据之前立即返回。因此,需要关注方法的返回的整数值,它表明了已经读到的字节数。

Non-blocking Mode with Selectors

非阻塞模式与选择器搭配会工作的更好,通过将一或多个SocketChannel注册到Selector,可以询问选择器哪个通道已经准备好了读取,写入等。Selector与SocketChannel的搭配使用会在后面详讲。