public void client() throws IOException {
//建立套接字通道
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 7878));
//切换到非阻塞模式
socketChannel.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(1024);
//从控制台输入
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String str = scanner.next();
//JDK8的时间类
LocalDateTime time = LocalDateTime.now();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String localTime = df.format(time);
buffer.put((localTime+"\n"+str).getBytes());
//pos,limit复位,切换到读取数据模式
buffer.flip();
//从缓冲区把数据写到管道
socketChannel.write(buffer);
buffer.clear();
}
scanner.close();
socketChannel.close();
}
public void server() throws IOException {
//建立套接字通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//切换到非阻塞模式
serverSocketChannel.configureBlocking(false);
//绑定对应服务端口,监听新的客户端连接
serverSocketChannel.bind(new InetSocketAddress(7878));
//获取选择器
Selector selector = Selector.open();
//向选择器中注册此通道和接受事件并监听
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//循环获取准备就绪的事件
while (selector.select() > 0) {
//获取当前选择器中所有注册的选择键,一个注册建对应一个某个感兴趣事件的通道
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
//获取准备就绪的事件
SelectionKey sk = iterator.next();
//判断是否已准备好接受新的套接字连接
if (sk.isAcceptable()) {
//获取接受就绪的客户端连接
SocketChannel socketChannel = serverSocketChannel.accept();
//切换非阻塞通道
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (sk.isReadable()) {
//通过
SocketChannel socketChannel = (SocketChannel) sk.channel();
//切换非阻塞通道
serverSocketChannel.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(1024);
int len = 0;
//从通道读取数据到缓冲区
while ((len = socketChannel.read(buffer)) > 0) {
buffer.flip();
System.out.println(new String(buffer.array(), 0, len));
buffer.clear();
}
}
}
//取消选择键,不然下次还会获取到
iterator.remove();
}
}
主要是服务端的代码
1.服务端的套接字管道要注册"接受监听事件"
2.Selector监听多个通道上感兴趣的事件,然后使用select()方法循环监听所有注册过的选择键是否有准备就绪的通道
3.遍历这些准备就绪的通道,看是哪种感兴趣事件
4.最后记得移除这些通道