网咯请求中的 connectTimeout 和 soTimeout
发布于: 2020 年 12 月 10 日
定义
在 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 日阅读数: 27
版权声明: 本文为 InfoQ 作者【不在调上】的原创文章。
原文链接:【http://xie.infoq.cn/article/eac0ff4dcfcdcc5a93ecbd9b2】。文章转载请联系作者。
不在调上
关注
还未添加个人签名 2018.04.28 加入
还未添加个人简介
评论