Java NIO多端口Socket服务端抛出ClosedChannelException与空指针异常问题
异常2:NullPointerException 定位与修复
触发原因
这是Java NIO Selector的经典易错点:selector.selectedKeys()返回的就绪事件键集合,不会自动删除已处理的键,必须手动调用迭代器的remove()方法移除已处理的键。你的代码没有做该操作,同一个ACCEPT事件的键会被反复遍历,第二次处理时没有新连接接入,ServerSocketChannel.accept()会返回null,后续调用null.socket()就会抛出空指针。
修复方案
在主服务端的迭代器循环中,取出键后立刻删除已处理的键:
while (selector.isOpen()) { try { selector.select(); Set readyKeys = selector.selectedKeys(); Iterator iterator = readyKeys.iterator(); System.out.println(readyKeys.size()); while (iterator.hasNext()) { SelectionKey key = (SelectionKey) iterator.next(); // 新增这行,手动移除已处理的键,避免重复遍历 iterator.remove(); if (key.isAcceptable()) { SocketChannel socketChannel = ((ServerSocketChannel) key.channel()).accept(); Socket socket = socketChannel.socket(); System.out.println("Accepted From: " + socket); DataInputStream dis = new DataInputStream(socket.getInputStream()); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); Thread t = new ClientHandler(socket, dis, dos); t.start(); } } } catch (Exception e) { e.printStackTrace(); System.exit(0); } }
额外优化建议
- 多上报端同时写
compiled.txt会有并发覆盖问题,上述修复代码中已经加了类锁保证写文件的原子性。 readUTF()最大仅支持64KB长度的字符串,如果你的新闻文件较大,建议改成字节流分段传输,避免抛出UTF数据长度超限异常。
内容的提问来源于stack exchange,提问作者user8331240
相关产品推荐
相关产品推荐

