欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

经过测试socket有 劳务派遣信息管理系统 个默认的超时时间

点击: 次  来源:宝鼎软件 时间:2017-09-03

原文出处: 囚兔

摘要: Java的网络编程Socket经常用于各类网络东西,好比数据库的jdbc客户端,redis客户端jedis,各类RPC东西java客户端,这个中存在一些参数来设置timeout,可是之前一直对timeout的领略还不清晰,所以会导致利用这些网络东西的时候有点苍茫。在此做个总结。

1. Socket timeout

Java socket有如下两种timeout:

  1. 成立毗连timeout,临时就叫 connect timeout;
  2. 读取数据timeout,临时就叫so timeout。

1.1 成立毗连connect timeout

当不配置该参数时,指客户端请求和处事端成立tcp毗连时,会一直阻塞直到毗连成立乐成,或抛异常。当配置了connectTimeout, 客户端请求和处事端成立毗连时,阻塞时间高出connectTimeout时,就会抛出异常java.net.ConnectException: Connection timed out: connect。

我们看如下精简后的代码,首先是处事端:

serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();

处事端开启ServerSocket监听8080端口,再看客户端:

socket = new Socket();
socket.connect(new InetSocketAddress("localhost", 8080));
System.out.println("Connected.");

打印“Connected.”,修改客户端代码中的主机名为一个不存在的主机:

    socket = new Socket();
    long t1 = 0;
    try {
        t1 = System.currentTimeMillis();
        socket.connect(new InetSocketAddress("www.ss.ssss", 8080));
    } catch (IOException e) {
        long t2 = System.currentTimeMillis();
        e.printStackTrace();
        System.out.println("Connect failed, take time -> " + (t2 - t1) + "ms.");
    }

抛出异常:java.net.ConnectException: Connection timed out: connect,并打印:Connect failed, take time -> 18532ms. 也就是当未配置connect timeout时,软件开发,connect要了解阻塞直到底层异常抛出。颠末测试socket有个默认的超时时间,或许在20秒阁下(测试的值,不必然精确,待研究JVM源码)。下面我们来配置connect timeout,再看看结果:

    socket = new Socket();
    long t1 = 0;
    try {
        t1 = System.currentTimeMillis();
        // 配置connect timeout 为2000毫秒
        socket.connect(new InetSocketAddress("www.ss.ssss", 8080), 2000);
    } catch (IOException e) {
        long t2 = System.currentTimeMillis();
        e.printStackTrace();
        System.out.println("Connect failed, take time -> " + (t2 - t1) + "ms.");
    }

抛出异常:java.net.SocketTimeoutException: connect timed out,并打印:Connect failed, take time -> 2014ms. 这里就是connect timeout发挥浸染了。

1.2 读取数据so timeout

先看下jdk源码注释:

Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. With this option set to a non-zero timeout, a read() call on the InputStream associated with this Socket will block for only this amount of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid. The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.

这个参数通过socket.setSoTimeout(int timeout)要领配置,可以看出它的意思是,socket关联的InputStream的read()要了解阻塞,直到高出配置的so timeout,就会抛出SocketTimeoutException。当不配置这个参数时,默认值为无穷大,即InputStream的read要了解一直阻塞下去,除非毗连断开。

下面通过代码来看下结果:

处事端代码:

serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();

处事端只接管socket但不发送任何数据给客户端。客户端代码:

socket = new Socket();
socket.connect(new InetSocketAddress("localhost", 8080));
System.out.println("Connected.");
in = socket.getInputStream();
System.out.println("reading...");
in.read();
System.out.println("read end");

客户端成立毗连就开始读取InputStream。打印:

Connected.
reading...

而且一直阻塞在in.read(); 上。接下来我配置so timeout,代码如下:

long t1 = 0;
try {
    socket = new Socket();
    socket.connect(new InetSocketAddress("localhost", 8080));
    // 配置so timeout 为2000毫秒
    socket.setSoTimeout(2000);
    System.out.println("Connected.");
    in = socket.getInputStream();
    System.out.println("reading...");
    t1 = System.currentTimeMillis();
    in.read();
} catch (IOException e) {
    long t2 = System.currentTimeMillis();
    System.out.println("read end, take -> " + (t2 - t1) + "ms");
    e.printStackTrace();
} finally {
    if (this.reader != null) {
        try {
            this.reader.close();
        } catch (IOException e) {
        }
    }
}

抛出异常:java.net.SocketTimeoutException: Read timed out, 打印:read end, take -> 2000ms , 说明so timeout起浸染了。

1.3 小结