ServerSocketChannel非阻塞监听连接需三步:先configureBlocking(false),再注册到Selector关注OP_ACCEPT,最后在select就绪后调用accept()获取SocketChannel。

ServerSocketChannel 在非阻塞模式下监听连接,核心是:设置为非阻塞、注册到 Selector、等待 OP_ACCEPT 事件,再调用 accept() 获取 SocketChannel。
1. 创建并配置 ServerSocketChannel
必须显式调用 configureBlocking(false),否则即使注册到 Selector 也无法触发就绪事件:
- 通过 ServerSocketChannel.open() 创建通道
- 绑定地址(bind)前需设置 SO_REUSEADDR(推荐)避免端口占用问题
- 立即调用 configureBlocking(false),这是非阻塞的前提
2. 注册到 Selector 并关注 OP_ACCEPT
Selector 是事件分发中心,ServerSocketChannel 只对 OP_ACCEPT 感兴趣:
- 创建 Selector(Selector.open())
- 调用 channel.register(selector, SelectionKey.OP_ACCEPT) 完成注册
- 注意:注册后不能直接调用 accept(),必须等 selector.select() 返回就绪才安全
3. 主循环:等待并处理连接就绪事件
典型服务端循环结构如下:
- 调用 selector.select() 阻塞等待事件(或 selectNow() 立即返回)
- 遍历 selectedKeys(),对每个 key 判断 isAcceptable()
- 在 isAcceptable() 为 true 时,调用 serverChannel.accept() 得到新的 SocketChannel
- 新 SocketChannel 也必须设为非阻塞,并注册到同一或另一个 Selector(如需读写)
4. 注意 accept() 的返回值和异常
非阻塞下 accept() 可能返回 null 或抛 ClosedChannelException:
- 返回 null 表示当前无新连接,不是错误,应继续循环
- 若底层 socket 已关闭,会抛 ClosedChannelException,需捕获并清理资源
- 新获得的 SocketChannel 默认也是非阻塞的,但建议显式调用 configureBlocking(false) 确保一致
不复杂但容易忽略。关键就是三步:非阻塞设置、Selector 注册、事件驱动 accept。

















