客户端
package com.company.Selector.Selector1;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
public class NIOClient {
public static void main(String[] args) throws Exception{
//打开通道
SocketChannel socketChannel = SocketChannel.open();
//设置为非阻塞
socketChannel.configureBlocking(false);
//绑定
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 6666);
if(!socketChannel.connect(inetSocketAddress)){
while (!socketChannel.finishConnect()){
System.out.println("连接失败");
}
}
while (true) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
System.out.println(str);
ByteBuffer byteBuffer = ByteBuffer.wrap(str.getBytes());
socketChannel.write(byteBuffer);
}
}
}
服务器
package com.company.Selector.Selector1;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class NIOServer {
public static void main(String[] args) throws Exception {
//打开ServerSocketChannel等待连接
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//设置非阻塞
serverSocketChannel.configureBlocking(false);
//绑定端口号6666
serverSocketChannel.socket().bind(new InetSocketAddress(6666));
//打开选择器
Selector selector = Selector.open();
//注册,监听连接事件
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true){
//循环监听
//select是阻塞方法
/* if ( selector.select(5000)==0){
System.out.println("没有客户端连接");
continue;
}*/
selector.select();
//获得存在事件的SelectionKey
Set<SelectionKey> selectionKeys = selector.selectedKeys();
//迭代Set集合
Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
while (keyIterator.hasNext()){
SelectionKey key = keyIterator.next();
if (key.isAcceptable()){
System.out.println("得到客户端连接");
//accept得到SocketChannel
SocketChannel socketChannel = serverSocketChannel.accept();
//设置非阻塞
socketChannel.configureBlocking(false);
//注册,socketChannel监听读事件
//关联一个bytebuffer
//socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
socketChannel.register(selector, SelectionKey.OP_READ);
}
if (key.isReadable()){
//SelectionKey的channel方法得到SocketChannel
SocketChannel socketChannel = (SocketChannel) key.channel();
//获得buffer
//ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//从通道读出数据
socketChannel.read(byteBuffer);
byteBuffer.clear();
System.out.println(new String(byteBuffer.array()));
}
keyIterator.remove();
}
}
}
}
总结
- Selector是一个选择器,用于处理非阻塞的通道,即一个线程设置一个选择器,可以处理多个通道
- Selector用于处理网络通道,常用的有ServerSocketChannel、SocketChannel,需要这些通道注册在Selector上才可以管理
- Selector有许多方法,其中select()方法监控所有通道,当有通道发生事件时,会将该通道的SelectionKey对象保存到集合
- SelectionKey是对象是一个标识对象,里面保存着许多属性,可以根据key反向获取通道信息,执行相关操作。