写点什么

网咯请求中的 connectTimeout 和 soTimeout

用户头像
不在调上
关注
发布于: 2020 年 12 月 10 日

定义

  1. 在 socket connect 阶段的 timeout 叫着 connectTimeout

  2. 在读数据的 timeout,叫做 soTimeout

建立连接的 connect timeout

当我们客户端对服务端建立连接的时候,可以设置超时时间,如果不设置,会一直阻塞知道连接建立成功,或者抛异常。当设置了 connect timeout ,客户端会阻塞到超过 connectTimeout,就会抛出异常

首先是没有设置阻塞时间


Socket socket = new Socket(); long t1 = 0; try { t1 = System.currentTimeMillis(); socket.connect(new InetSocketAddress("www.test11.com", 8089)); } catch (IOException e) { long t2 = System.currentTimeMillis(); e.printStackTrace(); System.out.println("Connect failed, take time -> " + (t2 - t1) + "ms."); }错误信息java.net.ConnectException: Operation timed out (Connection timed out) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:476) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:218) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:200) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394) at java.net.Socket.connect(Socket.java:606) at java.net.Socket.connect(Socket.java:555) at com.test.ymm.SocketClient.test1(SocketClient.java:39) at com.test.ymm.SocketClient.main(SocketClient.java:11)Connect failed, take time -> 76468ms.
复制代码

现在看看设置了 connect timeout 后的效果

 Socket  socket = new Socket();        long t1 = 0;        try {            t1 = System.currentTimeMillis();            socket.connect(new InetSocketAddress("www.test1234.com", 8089), 3000);        } 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	at java.net.PlainSocketImpl.socketConnect(Native Method)	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:476)	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:218)	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:200)	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:394)	at java.net.Socket.connect(Socket.java:606)	at com.test.ymm.SocketClient.test1(SocketClient.java:39)	at com.test.ymm.SocketClient.main(SocketClient.java:11)Connect failed, take time -> 3268ms.
复制代码

可以看到了 timeout 生效了

读取数据 sotimeout

先来看看 jdk 的注释

   /** Set a timeout on blocking Socket operations:     * <PRE>     * ServerSocket.accept();     * SocketInputStream.read();     * DatagramSocket.receive();     * </PRE>     *     * <P> The option must be set prior to entering a blocking     * operation to take effect.  If the timeout expires and the     * operation would continue to block,     * <B>java.io.InterruptedIOException</B> is raised.  The Socket is     * not closed in this case.     *     * <P> Valid for all sockets: SocketImpl, DatagramSocketImpl     *     * @see Socket#setSoTimeout     * @see ServerSocket#setSoTimeout     * @see DatagramSocket#setSoTimeout     */    @Native public final static int SO_TIMEOUT = 0x1006;         /**     *  Enable/disable {@link SocketOptions#SO_TIMEOUT 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 <B>java.net.SocketTimeoutException</B> is raised, though the     *  Socket is still valid. The option <B>must</B> be enabled     *  prior to entering the blocking operation to have effect. The     *  timeout must be {@code > 0}.     *  A timeout of zero is interpreted as an infinite timeout.     *     * @param timeout the specified timeout, in milliseconds.     * @exception SocketException if there is an error     * in the underlying protocol, such as a TCP error.     * @since   JDK 1.1     * @see #getSoTimeout()     */     public synchronized void setSoTimeout(int timeout) throws SocketException 
复制代码

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

先来看看未设置超时时间

Socket  socket = new Socket();        long t1 = 0;        try {            t1 = System.currentTimeMillis();            socket.connect(new InetSocketAddress("127.0.0.1", 8089));            System.out.println("Connected.");            InputStream in = socket.getInputStream();            System.out.println("reading...");            in.read();            System.out.println("read end");        } catch (IOException e) {            long t2 = System.currentTimeMillis();            e.printStackTrace();            System.out.println("Connect failed, take time -> " + (t2 - t1) + "ms.");        }         输出信息           Connected.reading...
复制代码

然后是设置超时时间

Socket  socket = new Socket();        long t1 = 0;        try {            t1 = System.currentTimeMillis();            socket.setSoTimeout(2000);            socket.connect(new InetSocketAddress("127.0.0.1", 8089));            System.out.println("Connected.");            InputStream in = socket.getInputStream();            System.out.println("reading...");            in.read();            System.out.println("read end");        } catch (IOException e) {            long t2 = System.currentTimeMillis();            e.printStackTrace();            System.out.println("Connect failed, take time -> " + (t2 - t1) + "ms.");        } 输出 信息         Connected.reading...java.net.SocketTimeoutException: Read timed out	at java.net.SocketInputStream.socketRead0(Native Method)	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)	at java.net.SocketInputStream.read(SocketInputStream.java:171)	at java.net.SocketInputStream.read(SocketInputStream.java:141)	at java.net.SocketInputStream.read(SocketInputStream.java:224)	at com.test.ymm.SocketClient.test1(SocketClient.java:44)	at com.test.ymm.SocketClient.main(SocketClient.java:11)Connect failed, take time -> 2017ms.   
复制代码

okhttp 超时机制

https://zhuanlan.zhihu.com/p/31640388


发布于: 2020 年 12 月 10 日阅读数: 27
用户头像

不在调上

关注

还未添加个人签名 2018.04.28 加入

还未添加个人简介

评论

发布
暂无评论
网咯请求中的 connectTimeout 和 soTimeout