使用SocketChannel发起非阻塞TCP连接需四步:1.创建通道并设为非阻塞后调用connect();2.注册到Selector监听OP_CONNECT;3.就绪后调用finishConnect()确认结果;4.处理成功、失败或超时。

使用 SocketChannel 发起非阻塞 TCP 连接,核心在于:先打开通道、设为非阻塞、调用 connect(),再通过 Selector 监听连接就绪事件(OP_CONNECT),最后检查并完成连接。
1. 创建并配置 SocketChannel
必须在调用 connect() 前将通道设为非阻塞模式,否则会抛出 IllegalBlockingModeException:
- 调用
SocketChannel.open()创建通道 - 立即执行
channel.configureBlocking(false) - 然后调用
channel.connect(new InetSocketAddress(host, port))
注意:此时 connect() 返回 false 表示连接尚未完成(正常行为),不是失败。
2. 注册到 Selector 并监听 OP_CONNECT
需要一个 Selector 来等待连接结果:
- 获取或创建
Selector(Selector.open()) - 调用
channel.register(selector, SelectionKey.OP_CONNECT) - 后续调用
selector.select()阻塞等待事件,或selectNow()立即返回
当 SelectionKey.isConnectable() 为 true,说明连接尝试已有结果(成功或失败)。
3. 完成连接并处理结果
在检测到 OP_CONNECT 就绪后,必须调用 channel.finishConnect():
- 若返回
true:连接成功,可开始读写(记得注册OP_READ或OP_WRITE) - 若返回
false:连接仍在进行中(极少见,通常可忽略) - 若抛出异常(如
IOException):连接失败(例如目标不可达、拒绝连接)
务必捕获异常并关闭通道,避免资源泄漏。
4. 实际使用中的关键细节
不能跳过 finishConnect() —— 即使 connect() 返回 true(在阻塞模式下才可能),非阻塞模式下必须显式调用它来确认状态。
- 连接超时需自行控制:
select(timeout)+ 计时器,或用System.nanoTime()判断耗时 - 连接成功后,建议立刻注册
OP_READ(如果要接收数据)或OP_WRITE(如果要发送首包) - 不要在未就绪时反复调用
finishConnect(),应等OP_CONNECT触发后再处理

















