Java连接不可达主机时如何设置Socket建立连接的超时时间
Java Socket跨系统连接超时设置方案
Java标准库本身提供了全操作系统适配的连接超时设置方法,你之前遇到的不同系统超时时间不一致的问题,是因为直接调用了带主机和端口参数的Socket构造方法,该方法没有暴露超时配置入口,会直接使用操作系统默认的连接超时阈值,才会出现Artix和Win10环境下超时时间差异巨大的情况。而你提到的setSoTimeout确实只作用于读写操作的超时,和连接阶段无关。
具体实现方式
使用无参构造方法创建Socket实例,再调用带超时参数的connect方法完成连接,第二个参数就是自定义的连接超时时间,单位为毫秒:
private static final int SAMPLESIZE = 32; // 自定义连接超时时间,这里设为5000即5秒,可按需调整 private static final int CONNECT_TIMEOUT = 5000; public static void main(String[] args) { long[] times = new long[SAMPLESIZE]; int tryNum = 0; long time; System.out.println("measuring timeout on opening a java.net.Socket to unreachable host...\n\n"); while(tryNum < times.length) { System.out.print("try #" + tryNum + "..."); time = System.currentTimeMillis(); Socket s = null; try { // 先创建无参Socket实例 s = new Socket(); // 调用带超时的connect方法完成连接 s.connect(new InetSocketAddress("192.168.15.15",12345), CONNECT_TIMEOUT); } catch (SocketTimeoutException e) { // 连接超时触发的异常,说明到了你设置的时间还没连上 } catch (IOException e) { // 其他连接异常,比如NoRouteToHostException、ConnectException都在这里捕获 } finally { if (s != null) { try { s.close(); } catch (IOException e) { // 关闭异常忽略即可 } } } times[tryNum] = System.currentTimeMillis() - time; System.out.println(times[tryNum] + "ms"); tryNum++; } System.out.println("\n\ntimes:"); long average = 0; tryNum = 0; for(long result : times) { System.out.print("#" + tryNum + ":" + result + "ms | "); average += result; tryNum++; } System.out.print("\b\b"); System.out.println("\n\naverage: " + Math.round(average/tryNum) + "ms"); }
注意事项
- 该方案是Java 1.4版本就纳入标准规范的API,所有主流JDK版本、所有支持Java运行的操作系统都可以通用,无需单独适配。
- 如果
connect方法的超时参数设为0,代表不设超时阈值,继续使用操作系统默认的连接超时逻辑。 - 自定义超时触发后抛出的是
SocketTimeoutException,可以和操作系统层面返回的NoRouteToHostException、ConnectException区分捕获,做不同的业务处理。
内容的提问来源于stack exchange,提问作者roediGERhard
相关产品推荐
相关产品推荐

