10.处理write写事件

java 复制代码
@Slf4j
public class NioServer {

    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        serverSocketChannel.bind(new InetSocketAddress(8000));
        while (true) {
            selector.select();
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            if(iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                //与客户端建立连接
                if(selectionKey.isAcceptable()) {
                    //因为ServerSocketChannel只有一个,可以直接使用
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    SelectionKey acceptKey = socketChannel.register(selector, 0, null);
                    acceptKey.interestOps(SelectionKey.OP_READ);

                    //向客户端发大量数据
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < 5000000; i++) {
                        sb.append("a");
                    }
                    ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(sb.toString());

                    //返回实际写的字节数
                    int write = socketChannel.write(byteBuffer);
                    log.info("write1={}", write);
                    if(byteBuffer.hasRemaining()) {
                        //添加关注写事件
                        acceptKey.interestOps(acceptKey.interestOps() + SelectionKey.OP_WRITE);
                        //把未写完的数据挂到selectKey上
                        acceptKey.attach(byteBuffer);
                    }
                } else if(selectionKey.isWritable()) {
                    ByteBuffer byteBuffer = (ByteBuffer)selectionKey.attachment();
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    int write = socketChannel.write(byteBuffer);
                    log.info("write2={}", write);
                    //清理操作
                    if(!byteBuffer.hasRemaining()) {
                        selectionKey.attach(null);//清除附件ByteBuffer
                        //不需要关注write事件
                        selectionKey.interestOps(selectionKey.interestOps() - SelectionKey.OP_WRITE);
                    }
                }
            }
        }
    }
}
java 复制代码
@Slf4j
public class NioClient {

    public static void main(String[] args) throws IOException {
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress("localhost", 8000));

        long totalCount = 0;
        while (true) {
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024 * 1024);
            int read = socketChannel.read(byteBuffer);
            totalCount += read;
            log.info("totalCount={}", totalCount);
            byteBuffer.clear();
        }
    }
}

相关推荐
ck-joker7 分钟前
M1 Pro跑LLM实测:Ollama+LangChain4j零成本本地大模型开发,比云端API快在哪?
java·语言模型
丙氨酸長鏈40 分钟前
[Bukkit插件开发]手持发射器箭矢机枪 教学文档 面向Python/C#开发者入门Java与Bukkit API
java·python·c#
Nontee42 分钟前
设计模式:模板方法与策略,从“每个字都认识“到能说清它们在干嘛
java·数据库·设计模式
我是唐青枫43 分钟前
Java ReentrantLock 实战详解:比 synchronized 更灵活的可重入锁
java·开发语言
晨曦中的暮雨2 小时前
Virtual Thread 优化 Spring AI 阻塞式 LLM I/O:对照压测报告
java·并发·个人项目
AKA__Zas2 小时前
芝士算法(前缀和2.0)
java·数据结构·算法·leetcode·哈希算法·学习方法
caishenzhibiao2 小时前
降雨带波段点差 同花顺期货通指标
java·c语言·c#
七夜zippoe3 小时前
OpenClaw Prompt 工程:从角色设定到 Skill 封装的 Agent 输出质量方法论
java·服务器·prompt·openclaw·skill封装
rosmis3 小时前
agent各指标定义
android·java·开发语言
mifengxing3 小时前
Java 集合进阶(一)
java·开发语言·数据结构·复习笔记