🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
案例代码:https://gitee.com/flymini/codes01/tree/master/example_/com-learn-nio01 **** 下面将实现多个 Client 与一个 Server 通信,Client 向 Server 发送数据,Server接收数据。 ![](https://img.kancloud.cn/aa/9c/aa9cd7d9dbe649f5e319f13744beb963_979x308.jpg) <br/> 步骤如下: **1. 编写服务端程序** ```java public class NioServer { // 选择器 private Selector selector; // 连接通道 private ServerSocketChannel listenChannel; public NioServer(int port) { try { selector = Selector.open(); listenChannel = ServerSocketChannel.open(); // 绑定端口 listenChannel.socket().bind(new InetSocketAddress(port)); // 设置非阻塞模式 listenChannel.configureBlocking(false); // 通道注册到selector listenChannel.register(selector, SelectionKey.OP_ACCEPT); } catch (Exception e) { e.printStackTrace(); } } public void listen() { System.out.println("服务端正在监听........."); try { while (true) { // 获取事件 if (selector.select() == 0) { continue; } Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); // 监听到不同的事件进行不同的处理 listenHandler(key); // 删除当前key,防止重复处理 iterator.remove(); } } } catch (Exception e) { e.printStackTrace(); } } /** * 针对监听到的不同事件做不同的处理 */ public void listenHandler(SelectionKey key) { SocketChannel sc = null; try { // 连接事件处理 if (key.isAcceptable()) { sc = listenChannel.accept(); // 设置非阻塞模式 sc.configureBlocking(false); // 通道注册到selector sc.register(selector, SelectionKey.OP_READ); } // 读取事件处理 if (key.isReadable()) { // 拿到socketChannel sc = (SocketChannel) key.channel(); // 设置非阻塞模式 sc.configureBlocking(false); ByteBuffer buffer = ByteBuffer.allocate(1024); // 读取消息数据 if (sc.read(buffer) > 0) { String msg = new String(buffer.array()); System.out.println("转发消息: " + msg); // 将消息转发 sendMsgToClient(msg); } } } catch (IOException e) { try { // 取消注册 key.cancel(); // 关闭通道 sc.close(); } catch (IOException e1) { e1.printStackTrace(); } } } /** * 发送消息到客户端 */ public void sendMsgToClient(String msg) throws IOException { for (SelectionKey key : selector.keys()) { Channel channel = key.channel(); if (channel instanceof SocketChannel) { SocketChannel targetChannel = (SocketChannel) channel; // 将msg写到buffer中 ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes()); // 将buffer数据写入通道 targetChannel.write(buffer); } } } public static void main(String[] args) { NioServer server = new NioServer(8888); server.listen(); } } ``` **2. 编写客户端程序** 客户端程序都是一样的,将下面的代码复制多份,文件名不同即可,就可以构建多个Client了。 ```java public class NioClientE { // 选择器 private Selector selector; // 连接通道 private SocketChannel socketChannel; // 用户名 private String username; // 启动标志位 private boolean flag; public NioClientE(String ip, int port, String username) { try { this.username = username; flag = true; selector = Selector.open(); // 连接服务器 socketChannel = SocketChannel.open(new InetSocketAddress(ip, port)); // 设置非阻塞 socketChannel.configureBlocking(false); // 连接通道注册到selector socketChannel.register(selector, SelectionKey.OP_READ); sendMsgToServer("上线了"); // 监听线程 ExecutorService executor = Executors.newSingleThreadExecutor(); // 循环读取服务端的消息 executor.execute(() -> { while (flag) { acceptMsgFromServer(); } }); executor.shutdown(); } catch (Exception e) { e.printStackTrace(); } } /** * 向服务端发送消息 */ public void sendMsgToServer(String msg) { msg = username + "," + msg; try { // 发送消息 socketChannel.write(ByteBuffer.wrap(msg.getBytes())); } catch (Exception e) { e.printStackTrace(); } } /** * 接收服务端发来的消息 */ public void acceptMsgFromServer() { try { if (selector.select() > 0) { Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext() && flag) { SelectionKey key = iterator.next(); if (key.isReadable()) { SocketChannel sc = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); sc.read(buffer); String msg = new String(buffer.array()); System.out.println(msg.trim()); // 移除当前的key,防止重复操作 iterator.remove(); } } } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { System.out.print("请输入用户名: "); Scanner scanner = new Scanner(System.in); String username = scanner.nextLine(); NioClientE client = new NioClientE("127.0.0.1", 8888, username); while (true) { // 发送数据到服务端 String msg = scanner.nextLine(); if (msg.equals("exit")) { try { client.flag = false; client.sendMsgToServer("下线了"); client.socketChannel.finishConnect(); client.selector.close(); break; } catch (IOException e) { e.printStackTrace(); } } else { client.sendMsgToServer(msg); } } } } ``` **3. 测试** 先启动服务端,然后分别启动客户端,我这里共有2个客户端程序。 ![](https://img.kancloud.cn/13/18/13181ab27134edf6714569ede46f8bcd_1397x221.gif)