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

设置方式

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

方式1:

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

方式2:

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

实际测试

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

第1种方式

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

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

ip :29.212.19.201,端口:2132

  1. public static void main(String[] args) {
  2. Socket socket = new Socket();
  3. SocketAddress endpoint = new InetSocketAddress("29.212.19.201", 2132);
  4. long timeMillis = System.currentTimeMillis();
  5. try {
  6. socket.connect(endpoint, 10000);
  7. } catch (IOException e) {
  8. e.printStackTrace();
  9. }
  10. System.out.println(System.currentTimeMillis()-timeMillis);
  11. System.out.println("end");
  12. }

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

  1. 10002
  2. java.net.SocketTimeoutException: connect timed out
  3. at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
  4. at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
  5. at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
  6. at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
  7. at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
  8. at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
  9. at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
  10. at java.net.Socket.connect(Socket.java:589)
  11. at com.wakling.cn.SocketSever.main(SocketSever.java:33)
  12. 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毫秒)连接超时。如下是不设置连接超时时间的代码:

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

第2种方式

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

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

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

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

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

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

  1. java.net.SocketTimeoutException: Read timed out
  2. at java.net.SocketInputStream.socketRead0(Native Method)
  3. at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
  4. at java.net.SocketInputStream.read(SocketInputStream.java:171)
  5. at java.net.SocketInputStream.read(SocketInputStream.java:141)
  6. at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
  7. at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
  8. at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
  9. at java.io.InputStreamReader.read(InputStreamReader.java:184)
  10. at java.io.BufferedReader.fill(BufferedReader.java:161)
  11. at java.io.BufferedReader.readLine(BufferedReader.java:324)
  12. at java.io.BufferedReader.readLine(BufferedReader.java:389)
  13. at com.wakling.cn.SocketClient.main(SocketClient.java:36)
  14. 10020
  15. 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. 内核态发生非法地址访问是否会panic

    https://mp.weixin.qq.com/s?__biz=MzAwMDUwNDgxOA==&mid=2652663676&idx=1&sn=b18ab57322594e ...

  2. jQuery 源码分析(十七) 事件系统模块 实例方法和便捷方法 详解

    实例方法和便捷方法是指jQuery可以直接通过链接操作的方法,是通过调用$.event上的方法(上一节介绍的底层方法)来实现的,常用的如下: on(types,selector,data,fn,one ...

  3. 这篇文章带你彻底理解synchronized

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  4. jQuery-File-Upload $(...).fileupload is not a function $.widget is not a function

    使用 jQuery-File-Upload 库的时候碰到了 $(...).fileupload is not a function  和 $.widget is not a function  问题. ...

  5. 渗透测试之wep无线网络破解

    WEP 无线网络破解 WEP(无线等效协议)于 1999 年诞生,并且是用于无线网络的最古老的安全标准.在 2003 年,WEP 被 WPA 以及之后被 WPA2 取代.由于可以使用更加安全的协议,W ...

  6. PyCharm注释中出现中文运行报错的解决办法

    SyntaxError: Non-UTF-8 code starting with '..... 方法一:在文件首行加上 # -*- coding:utf-8 -*- 方法二:更改编码格式 File ...

  7. jdk的一条命令查看运行参数

    jps 查看运行的java进程; jinfo <pid> 查看 jvm 配置参数

  8. golang数据结构和算法之QueueLinkedList链表队列

    队列和堆栈不一样的地方在于进出顺序: 堆栈是后进先出, 队列是先进先出. QueueLinkedList.go package QueueLinkedList type Node struct { d ...

  9. 1.Python网络编程_UDP(简略版)

    # -*- coding: utf-8 -*- #2019-11-24 import socket def recv(): udp_socket=socket.socket(socket.AF_INE ...

  10. UML图示样例