网咯请求中的 connectTimeout 和 soTimeout
作者:不在调上
- 2020-12-10
本文字数:3215 字
阅读完需:约 11 分钟
定义
在 socket connect 阶段的 timeout 叫着 connectTimeout
在读数据的 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阅读数: 783
版权声明: 本文为 InfoQ 作者【不在调上】的原创文章。
原文链接:【http://xie.infoq.cn/article/eac0ff4dcfcdcc5a93ecbd9b2】。文章转载请联系作者。
不在调上
关注
还未添加个人签名 2018-04-28 加入
还未添加个人简介









评论