finishConnect 返回 true 说明 TCP 三次握手已完成、socket 可读写,但不保证对端存活或应用层可达;必须在 OP_CONNECT 就绪后调用,且仅能调用一次,否则抛 IllegalStateException。

finishConnect 返回 true 说明连接已就绪,但不等于网络层已通
finishConnect() 是 SocketChannel 在非阻塞模式下确认连接是否完成的唯一可靠方式。它不阻塞,只检查底层连接状态:若返回 true,表示 TCP 三次握手已完成,socket 处于可读写状态;若返回 false,说明连接仍在进行中;若抛出异常(如 IOException),则连接失败(如拒绝连接、超时等)。
注意:它不检测对端是否存活或应用层是否可通信——只是确认本端 socket 的连接状态已就绪。
必须在 OP_CONNECT 就绪后调用 finishConnect
当 Selector 报告该 SocketChannel 的 OP_CONNECT 事件就绪时,才应调用 finishConnect()。在此之前调用会始终返回 false 或抛异常。
- 注册 channel 时需先调用
configureBlocking(false),再调用connect()(此时立即返回false) - 随后注册
OP_CONNECT到Selector,等待就绪 - 就绪后,必须调用
finishConnect()—— 即使只调一次,也不能跳过 - 成功后,记得取消
OP_CONNECT关注,并根据需要注册OP_READ或OP_WRITE
常见错误:忽略 finishConnect 的返回值或异常
很多开发者误以为 OP_CONNECT 就绪就等于连接成功,直接开始读写,结果触发 NotYetConnectedException 或写入静默失败。
正确做法是:
- 检查
finishConnect()返回值:true才算真正就绪 - 捕获并处理
IOException:如Connection refused、Timeout、No route to host - 不要在未调用
finishConnect()前调用read()或write() - 即使
finishConnect()返回true,首次write()仍可能因对端窗口为 0 而返回 0,需配合OP_WRITE处理
超时控制不能依赖 finishConnect 自身
finishConnect() 本身无超时参数,它只是瞬时状态检查。连接超时必须由上层控制:
- 记录
connect()调用时间,在每次select()循环中判断是否超时 - 超时后显式调用
close(),避免 channel 悬挂 - 不要指望
finishConnect()抛出SocketTimeoutException—— 它不会,TCP 层超时由系统决定,Java 层只反映当前状态 - 某些平台(如 Linux)在 SYN 包被丢弃时,可能长时间不通知失败,需靠定时器兜底
真正容易被忽略的是:连接成功后,finishConnect() 只能调用一次;重复调用会抛 IllegalStateException —— 这个限制常在重连逻辑里引发 bug。










