NIO基础入门(五)之Socket通道&管道

[TOC]

1.概念

socket通道与File通道的不同特征为:socket通道可以非阻塞模式并且可选,可以激活大程序巨大的可伸缩性灵活性

File通道I/O是阻塞模式(AIO更新后在使用时也可以做非阻塞)

没有必要为每个Socket通道分配一个线程的必要,也减小了频繁交换上下文开销,一个或几个线程可以管理成百上千的Socket活动,且性能损耗较小

全部的socket通道都是位于 java.nio.channels.spi包中的AbstractSelectableChannel引申而来

这意味着我们可以使用Selector对象来执行socket的有条件选择(选择和多路复用概念)

2.分类:

DatagramChannel和SocketChannel实现定义读写功能的接口

ServerSocketChannel不实现,它只负责监听传入的连接和创建新的SocketChannel对象,本身不传输数据

通道是一个连接I/O服务导管提供服务交互的方法,

就某个socket而言,他不会再次实现与之对应的socket通道类中的socket协议API

java.net中已存在的socket通道可以被大多数协议操作重复使用

全部Socket通道类(DatagramChannel/SocketChannel/ServerSocketChannel)在被实例化时

都会创建一个对等的socket对象,他们已经被更新以识别通道,在socket通道上使用socket()方法可以获得该对象

注意:传统的直接实例化socket对象,不会产生关联的socket通道,并且getChannel()方法返回也为空

3.非阻塞模式

Socket通道可以在非阻塞模式下运行,传统java Socket的阻塞曾经是java程序可伸缩性的重要约束之一

非阻塞I/O是许多复杂/高性能程序/框架的基础

要把一个Socket通道置于非阻塞模式,需要依靠所有socket通道的共有超级类SelectableChannel

SelectableChannel部分源码
1
2
3
public abstract SelectableChannel configureBlocking(boolean block) throws IOException;    //选择开启阻塞/非阻塞模式
public abstract boolean isBlocking(); //判断是否阻塞
public abstract Object blockingLock(); //返回一个非透明的对象引用,该对象时通道实现修改阻塞模式时内部使用,只有勇于此对象的锁的线程才能更改通道的阻塞模式(模式锁)
模式切换示例
1
2
3
4
5
6
7
8
9
10
SocketChannel socketChannel = SocketChannel.open();
Object lock = socketChannel.blockingLock();

synchronized (lock) { //可以用来限制模式切换
boolean blocking = socketChannel.isBlocking();
System.out.println(blocking); //true 默认阻塞
socketChannel.configureBlocking(false);
boolean blocking2 = socketChannel.isBlocking();
System.out.println(blocking2); //false 非阻塞模式
}

4.ServerSocketChannel

与ServerSocket方法意义相同,区别是能在非阻塞模式下运行

源码

1
2
3
4
public static ServerSocketChannel open() throws IOException //静态工厂方法创建ServerSocketChannel对象,返回一个未绑定的java.net.ServerSocket关联的通道,对等Socket可再次基础上使用socket()方法获得
public abstract SocketChannel accept() throws IOException;
public abstract ServerSocket socket();
public final int validOps()

两种模式的绑定

1
2
3
4
5
6
7
8
9
10
11
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
int port=8002;
//阻塞式监听
ServerSocket serverSocket = serverSocketChannel.socket();
// serverSocket.bind(new InetSocketAddress("localhost",port));
// Socket accept = serverSocket.accept();//同ServerSocket方法相同,会阻塞并等待socket传入

//非阻塞式监听
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(port));
serverSocketChannel.accept();

Channels工具类

位于java.nio.channels.channels

详情百度(各种转换)