Java.nio中的主要类
ServerSocketChannel:ServerSocket的替代类.
SocketChannel:Socket的替代类
Selector:为ServerSocketChannel监控接受就绪事件,为SocketChannel监控连接就绪,读就绪和写就绪事件
SelectionKey:代表ServerSocketChannel及SocketChannel向Selector注册事件句柄
向SocketChannel和ServerSocketChannel注册事件:
SelectionKey key=serverSocketChannel.register(selector,op)
Op的可选值
对于ServerSocketChannel只有一个事件:
(1)SelectionKye.OP_ACCEPT:接受连接就绪事件,表示至少有了一个客户连接,服务器可以接受这个连接
SocketChannel可能发生3种事件
(1)SelectionKey.OP_CONNECT:连接就为事件,表示客户与服务器的连接已经成功
(2)SelectionKey.OP_WRITE/OP_READ:写的就绪事件,表示已经可以向输出流写数据了SocketChannel提供了接受和发送的方法
可以使用:read(ByteBuffer)write(ByteBuffer)写入写出
ServerSocketChannel类
方法:(PS继承过SelectableChannel类的方法)
(1)open()静态方法获取ServerSocketChannel对象.
(2)accept同ServerSocket,不过获取的是SocketChannel,根据是否阻塞返回null还是阻塞,值得注意的是accept返回的SocketChannel是阻塞模式的使用configureBlocking更改模式
(3)socket() 返回关联的ServerSocket
SocketChannel类
此类是Socket类的替代类
方法:(PS继承过SelectableChannel类的方法)
(1)open() open(SocketAddress)静态方法用来创建SocketChannel对象,第二个重写还会建立于远程服务器的连接.
(2)socket()返回关联的Socket对象
(3)isConnected()是否建立连接
(4)isConnectionPending判断是否正在进行远程连接
(5)connect() 建立远程连接() 根据是否阻塞而不同
(6)finishConnect() 视图完成远程连接
(7)read()读取数据(这个应该是接数据)
(8)write()写数据(这个是发送数据)
声明:
public static int PORT = 8888; ServerSocketChannel serverChannel; ServerSocket serverSocket; Selector selector;
初始化:
// 1. 分配一个 ServerSocketChannel 文件描述符 serverChannel = ServerSocketChannel.open(); // 2. 从 ServerSocketChannel里获取一个对于的 socket serverSocket = serverChannel.socket(); // 3. 生成一个 Selector selector = Selector.open(); // 4. 把 socket 绑定到端口上 serverSocket.bind(new InetSocketAddress(iport)); // 5. serverChannel 未非bolck serverChannel.configureBlocking(false); // 6. 通过Selector注册ServerSocketChannel: 只能注册 accept // 而SocketChannel可以注册CONNENCT,READ,WRITE ; register -> validOps // 在各个子类实现不同 serverChannel.register(selector, SelectionKey.OP_ACCEPT);
开启服务:
while (true) { try { // 获得IO准备就绪的channel数量 int n = selector.select(); // 没有channel准备就绪,继续执行 if (n == 0) { continue; } // 用一个iterator返回Selector的selectedkeys Iterator it = selector.selectedKeys().iterator(); // 处理每一个SelectionKey while (it.hasNext()) { SelectionKey key = (SelectionKey) it.next(); // 判断是否有新的连接到达 if (key.isAcceptable()) { // 返回SelectionKey的ServerSocketChannel ServerSocketChannel server = (ServerSocketChannel) key .channel(); System.out.println("有连接"); SocketChannel channel = server.accept(); registerChannel(selector, channel, SelectionKey.OP_READ); doWork(channel); } // 判断是否有数据在此channel里需要读取 if (key.isReadable()) { processData(key); } } // 删除 selectedkeys it.remove(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }