java-nio

原理图:

服务端:

package xyz.idoly.demo.nio;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class NioServer {

    private static final int PORT = 8080;

    public static void main(String[] args) throws IOException {
        // 1. 创建 ServerSocketChannel 并绑定端口
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.bind(new InetSocketAddress(PORT));
        serverChannel.configureBlocking(false); // 非阻塞模式

        // 2. 创建 Selector 并注册 ServerSocketChannel
        Selector selector = Selector.open();
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("NIO 服务器已启动,监听端口:" + PORT);

        // 3. 事件循环处理
        while (true) {
            selector.select(); // 阻塞等待事件

            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove(); // 处理后删除,避免重复处理
                
                if (key.isAcceptable()) {
                    handleAccept(serverChannel, selector);
                } else if (key.isReadable()) {
                    handleRead(key);
                }
            }
        }
    }

    private static void handleAccept(ServerSocketChannel serverChannel, Selector selector) throws IOException {
        SocketChannel clientChannel = serverChannel.accept(); // 接收连接
        clientChannel.configureBlocking(false);
        clientChannel.register(selector, SelectionKey.OP_READ);
        System.out.println("新客户端连接:" + clientChannel.getRemoteAddress());
    }

    private static void handleRead(SelectionKey key) throws IOException {
        SocketChannel clientChannel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int bytesRead = clientChannel.read(buffer);
        
        if (bytesRead == -1) {
            clientChannel.close(); // 关闭连接
            System.out.println("客户端断开连接");
            return;
        }

        buffer.flip();
        String message = new String(buffer.array(), 0, buffer.limit());
        System.out.println("收到消息:" + message);
        
        // 回显消息
        buffer.rewind();
        clientChannel.write(buffer);
    }
}
NIO 服务器已启动,监听端口:8080
新客户端连接:/127.0.0.1:56740
收到消息:Hello, NIO Server!
客户端断开连接

客户端:

package xyz.idoly.demo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class NioClient {
    private static final String SERVER_HOST = "127.0.0.1";
    private static final int SERVER_PORT = 8080;
    
    public static void main(String[] args) throws IOException {
        // 1. 打开 SocketChannel 并设置为非阻塞模式
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);

        // 2. 打开 Selector,并注册 CONNECT 事件
        Selector selector = Selector.open();
        socketChannel.register(selector, SelectionKey.OP_CONNECT);
        socketChannel.connect(new InetSocketAddress(SERVER_HOST, SERVER_PORT));

        // 3. 监听事件
        while (true) {
            selector.select(); // 阻塞直到有事件就绪

            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove(); // 避免重复处理

                if (key.isConnectable()) {
                    handleConnect(key);
                } else if (key.isWritable()) {
                    handleWrite(key);
                } else if (key.isReadable()) {
                    handleRead(key);
                }
            }
        }
    }

    private static void handleConnect(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        if (channel.finishConnect()) { // 完成连接
            System.out.println("连接服务器成功!");
            channel.configureBlocking(false);
            // 连接成功后,注册 WRITE 事件,准备发送数据
            channel.register(key.selector(), SelectionKey.OP_WRITE);
        }
    }

    private static void handleWrite(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        String message = "Hello, NIO Server!";
        ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
        channel.write(buffer);
        System.out.println("发送消息:" + message);

        // 发送完毕后,注册 READ 事件,等待服务器响应
        channel.register(key.selector(), SelectionKey.OP_READ);
    }

    private static void handleRead(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int bytesRead = channel.read(buffer);
        if (bytesRead > 0) {
            buffer.flip();
            String response = new String(buffer.array(), 0, buffer.limit());
            System.out.println("收到服务器响应:" + response);

            // 读取完成后,关闭通道
            channel.close();
        }
    }
}
连接服务器成功!
发送消息:Hello, NIO Server!
收到服务器响应:Hello, NIO Server!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值