SocketChannel



基本概念


  • Java NIO​中的​SocketChannel​是一个连接到​TCP​网络套接字的通道
  • 创建​SocketChannel​有两种方式:

  • 打开一个​SocketChannel​并连接到互联网上的某台服务器
  • 一个新连接到达​ServerSocketChannel​时,会创建一个​SocketChannel


SocketChannel的开启

  • 打开一个​SocketChannel:
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(url, 80);

SocketChannel的关闭

  • 当使用完毕​SocketChannel​之后调用​SocketChannel.close()​ 方法关闭​SocketChannel:
socketChannel.close();

从SocketChannel中读取数据

  • 通过调用​SocketChannel​中的​read()​ 方法从SocketChannel中读取数据
ByteBuffer buffer = ByteBuffer.allocate(64);
int bytesRead = SocketChannel.read(buffer);

  • 首先,分配一个Buffer,从SocketChannel读取到的数据将会存放到这个Buffer中
  • 然后,调用SocketChannel.read()方法,该方法将数据从SocketChannel读取到Buffer中:

  • read()​ 方法返回的​int​值表示读取了多少字节进​Buffer​里
  • 如果返回的是 ​-1,​ 表示已经读到了​Socket​流的末尾,连接关闭了


向SocketChannel中写入数据


  • 通过调用​SocketChannel.write()​ 方法向​SocketChannel​中写入数据
  • write()​ 方法以一个​Buffer​作为参数

ByteBuffer buffer = ByteBuffer.allocate(64);
buffer.clear();
buffer.put(data.getBytes());
buffer.flip();
while (buffer.hasRemaining()) {
socketChannel.write(buffer);
}

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

非阻塞模式


  • 可以设置​SocketChannel​为非阻塞模式​non-blocking model
  • 设置之后,就可以在异步模式下调用​connect(),read()​ 和​write()​ 方法

connect()


  • 如果​SocketChannel​在非阻塞模式下,此时调用​connect(),​ 该方法可能在连接建立之前就返回了
  • 为了确定连接是否建立,可以调用​finishConnect()​ 方法

socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress(url, 80));
while(!sockeChannel.finishConnect()) {
// 等待连接建立或者进行其余操作
}

write()


  • 非阻塞模式下 ​,write()​ 方法在尚未写出任何内容时可能就返回了
  • 所以需要在循环中调用​write()

read()


  • 非阻塞模式下 ​,read()​ 方法在尚未读取到任何数据时可能就返回了
  • 所以需要关注返回的​int​值 ​,int​的值表示读取了多少字节

非阻塞模式与选择器


非阻塞模式与选择器​Selector​结合起来一起使用通过将一个或者多个​SocketChannel​注册到​Selector​中,可以询问选择器​Selector​哪个通道已经准备好了读取,写入等