NIO基础通讯
服务端
package com.pw.datastructure.nio; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.util.Iterator; import java.util.Set; /** * @author pw * @version 1.0 * @date 2022/9/1 14:55 * 服务端 */ public class NIOServer { public static void main(String[] args) throws Exception{ //1. 创建socket服务通道: ServerSocketChannel -> ServerSocket (java) ServerSocketChannel socketChannel = ServerSocketChannel.open(); // 2. 创建一个选择器:selector Selector selector = Selector.open(); // 3. 绑定服务端监听端口 socketChannel.socket().bind(new InetSocketAddress(6666)); // 4. 设置ServerSocketChannel为非阻塞的 socketChannel.configureBlocking(false); // 5.将ServerSocketChannel 注册进 selector, 设置监听的事件是 ACCEPT (客户端连接时) socketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true){ // 阻塞1秒selector.select()阻塞多长时间 ,如果有事件发生方法会返回SelectionKey if(selector.select(1000) == 0){ // 在阻塞的1秒内没有客户端连接 System.out.println("服务器1秒内没有客户端连接~"); continue; } // 有客户端进行连接 // 1. 先拿到注册在selector的选择器集合 SelectionKey // 2. 拿到SelectionKey对应的ServerSocketChannel通道 Set<SelectionKey> selectionKeys = selector.selectedKeys(); // 遍历集合 Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()){ SelectionKey key = iterator.next(); // 拿到key找到对应的通道,处理相应的事件 if (key.isAcceptable()){ // 如果是连接事件 SocketChannel channel = socketChannel.accept(); System.out.println("客户端连接成功 生成了一个socketChannel"); // channel定义为非阻塞的 channel.configureBlocking(false); // 将SocketChannel注册到selector中,关注事件设置为OP_READ,同时给SocketChannel关联传输数据的ByteBuffer channel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024)); } if (key.isReadable()){ // 如果是可读事件 // 通过key反向获取对应的channel (这里的channel不需要定义为非阻塞的,因为拿到channel里的数据后直接进行处理) SocketChannel channel = (SocketChannel) key.channel(); // 获取channel对应的buffer ByteBuffer buffer = (ByteBuffer) key.attachment(); // 获取通道里面的数据 channel.read(buffer); System.out.println("客户端发送的数据是:"+new String(buffer.array()) ); } // 手动将集合中移除当前的selectionKey,防止多线程中iterator被重复拿到操作 iterator.remove(); } } } }
客户端
package com.pw.datastructure.nio; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; /** * @author pw * @version 1.0 * @date 2022/9/9 10:38 */ public class NIOClient { public static void main(String[] args) throws Exception { // 建立一个网络通道 SocketChannel socketChannel = SocketChannel.open(); // 设置成非阻塞通道 socketChannel.configureBlocking(false); // 提供服务器端的ip和端口 InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 6666); // 连接服务器 if (!socketChannel.connect(inetSocketAddress)){ // 非阻塞循环 while (!socketChannel.finishConnect()){ System.out.println("连接需要事件,客户端非阻塞,可以进行其他工作。。。。"); } } // 如果连接成功,就发送数据进行交互。 String msg = "hello ,socket"; // ByteBuffer.wrap(包裹):自动识别msg字节数组的大小,创建相同大小的byteBuffer ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes()); // 发送数据,将byteBuffer数据写入到channel中 socketChannel.write(byteBuffer); System.in.read(); } }