你知道在 Java 中怎么对 Socket 设置超时时间吗?他们的区别是什么?想一想和女朋友打电话的场景就知道了,如果实在想不到,那我们就一起来来看一下是咋回事吧

设置方式

主要有以下两种方式,我们来看一下

方式1:

Socket s=new Socket();
s.connect(new InetSocketAddress(host,port),10000);

方式2:

Socket s=new Socket("127.0.0.1",8080);
s.setSoTimeout(10000);

实际测试

那么这两种方式设置的超时时间各自代表了什么意义呢?有什么区别呢?

第1种方式

我们先来看一下第一种方式,我们来测试一下:

在main方法中我们创建 Socket 连接到

ip :29.212.19.201,端口:2132

public static void main(String[] args) {
Socket socket = new Socket();
SocketAddress endpoint = new InetSocketAddress("29.212.19.201", 2132);
long timeMillis = System.currentTimeMillis();
try {
socket.connect(endpoint, 10000);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis()-timeMillis);
System.out.println("end");
}

运行这段代码,控制台10秒之前没有任何信息输出,10秒后打印如下信息:

10002
java.net.SocketTimeoutException: connect timed out
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at com.wakling.cn.SocketSever.main(SocketSever.java:33)
end

可以看出,我们尝试连接到29.212.19.201:2132时,

连接了10秒都没有连接上,

于是就报了 java.net.SocketTimeoutException: connect timed out 的异常。

解释一下,上述的 IP 是一个未知的 IP ,即我的 IP 在当前网络环境中访问不到这个 IP ,这样我们的这个 Socket 才会去一直尝试连接到此 IP 直到超时。如果 IP 是一个已知的 IP ,例如本地 127.0.0.1 加上一个未知的端口,那么此 Socket 连接会立马报错。

另外,在不设置连接超时时间的情况下,Socket 默认大概是21s(测试了3次都是21020毫秒)连接超时。如下是不设置连接超时时间的代码:

Socket socket = new Socket("29.212.19.201", 2132);

第2种方式

然后我们来看一下第2种方式,这时候我们需要在我们本地写一套 Socket 服务以及客户端来模拟这个场景。

我们让客户端设置 setSoTimeout 为10s,在服务端代码拿到客户端请求信息后,休眠10s后再处理客户端请求,返回响应。

我们来看一下效果,关键代码如下:

//服务端
System.out.println("进入休眠,10s后醒来");
Thread.sleep(10000);
System.out.println("休眠结束");
//返回响应
OutputStream outputStream = socket.getOutputStream();// 获取一个输出流,向服务端发送信息
PrintWriter printWriter = new PrintWriter(outputStream);// 将输出流包装成打印流
printWriter.print("你好,服务端已接收到您的信息");
printWriter.flush();

//客户端
Socket socket = new Socket("127.0.0.1",2132);
socket.setSoTimeout(10000);//read的超时时间

运行后,等待客户端输出,10s后客户端控制台输出信息如下:

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 sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.wakling.cn.SocketClient.main(SocketClient.java:36)
10020
end

这里10s后客户端报错 java.net.SocketTimeoutException: Read timed out

查看客户端控制台信息正常输出,即使客户端已报超时,服务端仍然继续往下走,只是客户端已经收不到服务端10s后发给自己的消息。

另外经测试发现,服务端休眠很久很久,如500s,在客户端不设置 setSoTimeout 时,客户端默认120s超时。
对于 setSoTimeout 方法官方给的解释是这样的,我不知道超时时间设置为0是否真的为无穷大超时,感兴趣的可以试一下。

setSoTimeout

public void setSoTimeout(int timeout)

   throws SocketException启用/禁用带有指定超时值

   SO_TIMEOUT,以毫秒为单位。将此选项设为非零的超时值时,

      在与此 Socket 关联的 InputStream 上调用 read() 将只阻塞此时间长度

      如果超过超时值,将引发 java.net.SocketTimeoutException,虽然 Socket 仍旧有效。

      选项必须在进入阻塞操作前被启用才能生效。

   超时值必须是 > 0 的数。超时值为 0 被解释为无穷大超时值

参数:timeout - 指定的以毫秒为单位的超时值。

抛出:SocketException - 如果底层协议出现错误,例如 TCP 错误。

从以下版本开始:JDK 1.1

另请参见:getSoTimeout()

区别和意义

下面我们就来说一说二者的意义和区别。

方式1是客户端与服务端进行连接的超时时间,即10秒内建立不了连接就报 java.net.SocketTimeoutException: connect timed out 连接超时的异常.此时二者未建立连接,更别说服务端收到客户端的消息了

方式2是设置 inputStream.read() 方法的阻塞时间,即客户端发出请求后等待服务端返回响应的等待时长,超过这个时长将会引发 java.net.SocketTimeoutException: Read timed out 读取超时的异常。此时二者正常建立连接,服务端接收到了客户端的请求。

合理设置超时时间对增加程序的吞吐量和加强程序的健壮性有较为重大的意义。

两种方式控制超时的侧重点不同,就像女朋友给你打电话一样,她是有小脾气的。如果她按方法1对待你,那就是拨出去电话10秒内你不接电话她就挂了,如果她按方法2,那就是打电话接通后,假如你正在忙她就等你10秒,10秒内不说话就挂,10秒后说不说话她都听不到了,你就悲催了。

转载请注明出处

Socket超时时间设置的更多相关文章

  1. unigui session超时时间设置

    unigui session超时时间设置 默认的SESSION超时时间是10分钟. 网络 SOCKET 程序,像 数据库,中间件,UNIGUI等...为了防止过多的僵死连接卡死服务端,服务端都会主动踢 ...

  2. (转)nginx限制上传大小和超时时间设置说明/php限制上传大小

    nginx限制上传大小和超时时间设置说明/php限制上传大小 原文:http://www.cnblogs.com/kevingrace/p/6093671.html 现象说明:在服务器上部署了一套后台 ...

  3. session超时时间设置方法

    session超时时间设置方法 由于session值之前没有设置,以至于刚登录的网站,不到一分钟就超时了,总结了一下,原来是session过期的原因,以下是设置session时间的3个方法: 1. 在 ...

  4. GS 服务器超时时间设置

    工作中 遇到一个超时的问题 与徐庆同学沟通后 了解了下超时时间设置的地方 1.web.congfig问题: 常规路径 C:\Program Files\GenerSoft\bscw_local\web ...

  5. 接口调试工具ApiPost的发送超时时间设置方法

    有部分使用ApiPost的同学反应:发送接口调试时,响应超时时间设置的太短导致接口访问失败,怎么设置呢? 就连百度也有很多人在搜: 今天就来说一说. ApiPost简介: ApiPost是一个支持团队 ...

  6. MYSQL的数据连接超时时间设置

    大规模多线程操作事务的时候,有时候打开一个链接,会进行等待,这时候如果数据库的超时时间设置的过短,就可能会出现,数据链接自动被释放,当然设置过大也不好,慢SQL或其他因素引起的链接过长,导致整个系统被 ...

  7. 【Hadoop】Hadoop DataNode节点超时时间设置

    hadoop datanode节点超时时间设置 datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间 ...

  8. session的工作原理、django的超时时间设置及session过期判断

    1.session原理 cookie是保存在用户浏览器端的键值对 session是保存在服务器端的键值对 session服务端中存在的数据为: session = { 随机字符串1:{ 用户1的相关信 ...

  9. httpclient超时时间设置及代理设置

    超时时间 设置HttpClient的超时时间,非常有必要性,因为httpclient 默认超时时间很长,自己可以测试一下是多久,设置超时时间否则会影响自己系统的业务逻辑,例如阻塞系统,影响系统的吞吐量 ...

随机推荐

  1. 【CF528E】Triangles 3000(计算几何)

    [CF528E]Triangles 3000(计算几何) 题面 CF 平面上有若干条直线,保证不平行,不会三线共点. 求任选三条直线出来围出的三角形的面积的期望. 题解 如果一定考虑直接计算这个三角形 ...

  2. node.js箭头函数使用

    ES6允许使用=>定义函数,箭头函数使得表达更加简洁,例如 // 正常函数写法 [1,2,3].map(function (x) { return x * x; }); // 箭头函数写法 [1 ...

  3. sql server 查询出整数 (可灵活运用)

    系统辅助用表,常用来获取数字,当然还有其他用途

  4. go实现整型的二进制转化

    go中已经实现了int->bin的转化函数,我这里只是化过程逻辑的实现,至于原理我就假设大家都知道了 本案例只考虑 int->bin  的转化 包含了正整数,负整数,0 的转化 packa ...

  5. 再来五道剑指offer题目

    再来五道剑指offer题目 6.旋转数组的最小数字 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4, ...

  6. 【C#】学习笔记(1) Delegates,Events,Lambda Expressions

    C#是跟着杨老师的教程走的,在这里感谢一下老师的无私奉献,他的cnblog地址:>cgzl,他的B站地址:>solenovex. 进入正题: Delegate表示委托,委托是一种数据结构, ...

  7. u盘 安装 centOS 7

    实际上, 对于服务器的安装, 最好是能够远程批量安装(可能有些难度, 不是专业运维) 镜像下载地址: http://59.80.44.49/isoredirect.centos.org/centos/ ...

  8. 如何开发优质的 Flutter App:Flutter App 软件测试指南

    继上一场GitChat文章发布之后,博主又为朋友们带来另一场Chat.这一次我们主要聊一聊Flutter App的测试环节. 众所周知,应用的功能越多,手动测试的难度就越大.一套完整的自动化测试将帮助 ...

  9. [转]Eclipse插件开发之基础篇(6) SWT简介

    原文地址:http://www.cnblogs.com/liuzhuo/archive/2010/09/01/eclipse_plugin_1_3_1.html SWT(Standard Widget ...

  10. linux环境下安装selenium+chrom+chromdriver.exe

    原文:https://blog.csdn.net/yoyocat915/article/details/80580066 原文:https://blog.csdn.net/hanxue6898/art ...