iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >JavaSocket设置timeout的几种常用方式说明
  • 548
分享到

JavaSocket设置timeout的几种常用方式说明

JavaSocketSocket设置timeoutJavaSocket设置timeout 2022-11-13 19:11:01 548人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录1. Socket timeout1.1 建立连接connect timeout1.2 读取数据so timeout1.3 小结2. 使用案例2.1 Mysql jdbc tim

Java的网络编程Socket常常用于各种网络工具,比如数据库的jdbc客户端,Redis客户端jedis,各种rpc工具java客户端,这其中存在一些参数来配置timeout,但是之前一直对timeout的理解还不清晰,所以会导致使用这些网络工具的时候有点迷茫。在此做个总结。

1. Socket timeout

Java socket有如下两种timeout:

  • 建立连接timeout,暂时就叫 connect timeout
  • 读取数据timeout,暂时就叫so timeout 

1.1 建立连接connect timeout

当不设置该参数时,指客户端请求和服务端建立tcp连接时,会一直阻塞直到连接建立成功,或抛异常。当设置了connectTimeout, 客户端请求和服务端建立连接时,阻塞时间超过connectTimeout时,就会抛出异常java.net.ConnectException: Connection timed out: connect。

我们看如下精简后的代码,首先是服务端:

serverSocket = new ServerSocket(8080); 
Socket socket = serverSocket.accept(); 

服务端开启ServerSocket监听8080端口,再看客户端:

socket = new Socket(); 
socket.connect(new InetSocketAddress("localhost", 8080)); 
System.out.println("Connected.");

打印“Connected.”,修改客户端代码中的主机名为一个不存在的主机:

socket = new Socket(); 
long t1 = 0; 
try { 
t1 = System.currentTimeMillis(); 
socket.connect(new InetSocketAddress("www.ss.ssss", 8080)); 
} catch (IOException e) { 
long t2 = System.currentTimeMillis(); 
e.printStackTrace(); 
System.out.println("Connect failed, take time -> " + (t2 - t1) + "ms."); 
}

抛出异常:java.net.ConnectException: Connection timed out: connect,并打印:Connect failed, take time -> 18532ms. 也就是当未设置connect timeout时,connect方法会阻塞直到底层异常抛出。经过测试socket有个默认的超时时间,大概在20秒左右(测试的值,不一定准确,待研究JVM源码)。

下面我们来设置connect timeout,再看看效果:

socket = new Socket(); 
long t1 = 0; 
try { 
t1 = System.currentTimeMillis(); 
// 设置connect timeout 为2000毫秒 
socket.connect(new InetSocketAddress("www.ss.ssss", 8080), 2000); 
} 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,并打印:Connect failed, take time -> 2014ms. 这里就是connect timeout发挥作用了。

1.2 读取数据so timeout

先看下jdk源码注释:

Enable/disable 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 java.net.SocketTimeoutException is raised, though the Socket is still valid. The option must be enabled prior to entering the blocking operation to have effect.

The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.    

这个参数通过socket.setSoTimeout(int timeout)方法设置,可以看出它的意思是,socket关联的InputStream的read()方法会阻塞,直到超过设置的so timeout,就会抛出SocketTimeoutException。

当不设置这个参数时,默认值为无穷大,即InputStream的read方法会一直阻塞下去,除非连接断开。

下面通过代码来看下效果:

服务端代码:

serverSocket = new ServerSocket(8080); 
Socket socket = serverSocket.accept(); 

服务端只接受socket但不发送任何数据给客户端。客户端代码:

socket = new Socket(); 
socket.connect(new InetSocketAddress("localhost", 8080)); 
System.out.println("Connected."); 
in = socket.getInputStream(); 
System.out.println("reading..."); 
in.read(); 
System.out.println("read end");

客户端建立连接就开始读取InputStream。打印:

Connected.
reading...

并且一直阻塞在in.read(); 上。接下来我设置so timeout,代码如下:

long t1 = 0; 
try { 
socket = new Socket(); 
socket.connect(new InetSocketAddress("localhost", 8080)); 
// 设置so timeout 为2000毫秒 
socket.setSoTimeout(2000); 
System.out.println("Connected."); 
in = socket.getInputStream(); 
System.out.println("reading..."); 
t1 = System.currentTimeMillis(); 
in.read(); 
} catch (IOException e) { 
long t2 = System.currentTimeMillis(); 
System.out.println("read end, take -> " + (t2 - t1) + "ms"); 
e.printStackTrace(); 
} finally { 
if (this.reader != null) { 
try { 
this.reader.close(); 
} catch (IOException e) { 
} 
} 
}

抛出异常:java.net.SocketTimeoutException: Read timed out, 打印:read end, take -> 2000ms , 说明so timeout起作用了。

1.3 小结

我们可以通过设置connect timeout来控制连接建立的超时时间(不是绝对的,当设置的主机名不合法,比如我设置主机名为abc,会抛异常java.net.UnknownHostException: abc,但是此时connect timeout设置是不起作用的,测试得出的结论,仅供参考)。

通过设置so timeout可以控制流读取数据的超时时间。

2. 使用案例

2.1 mysql jdbc timeout

查阅Mysql Connector/J 5.1 Developer Guide 中的jdbc配置参数,有

connectTimeout

Timeout for socket connect (in milliseconds), with 0 being no timeout. Only works on JDK-1.4 or newer. Defaults to '0'.

Default: 0

Since version: 3.0.1

socketTimeout

Timeout on network socket operations (0, the default means no timeout).

Default: 0

Since version: 3.0.1

这两个参数分别就是对应上面我们分析的connect timeout和so timeout。

参数的设置方法有两种,一种是通过url设置,

jdbc:mysql://[host1][:port1][,[host2][:port2]]...[/[database]] [?propertyName1=propertyValue1[&propertyName2=propertyValue2]...]

即在url后面通过?加参数,比如

jdbc:mysql://192.168.1.1:3306/test?connectTimeout=2000&socketTime=2000

还有一种方式是:

Properties info = new Properties(); 
info.put("user", this.username); 
info.put("passWord", this.password); 
info.put("connectTimeout", "2000"); 
info.put("socketTime", "2000"); 
return DriverManager.getConnection(this.url, info); 

2.2 Jedis timeout

Jedis是最流行的redis java客户端工具,redis.clients.jedis.Jedis对象的构造器中就有参数设置,

public Jedis(final String host, final int port, final int connectionTimeout, final int soTimeout) { 
super(host, port, connectionTimeout, soTimeout); 
} 
// 用一个参数timeout同时设置connect timeout 和 so timeout 
public Jedis(final String host, final int port, final int timeout) { 
super(host, port, timeout); 
}

Jedis中so timeout个人觉得是有比较重要意义的,首先jedis so timeout默认值为2000毫秒,jedis的操作流程是客户端发送命令给服务器端执行,然后客户端就开始执行InputStream.read()读取响应,当某个命令比较耗时(比如数据非常多的情况下执行“keys *”),而导致客户端迟迟没有收到响应,就可能导致java.net.SocketTimeoutException: Read timed out异常抛出。

一般是不建议客户端执行非常耗时的命令,但是也不排除有这种特殊逻辑,那这时候就有可能需要修改Jeids中这个so timeout的值。

3. 总结

了解了这两个timeout之后,可以更好的处理一些网络服务的客户端和服务端,同时对排查一些问题也很有帮助。

一般的成熟的网络服务和客户端都应该有这两个参数的配置方法,当使用遇到类似问题可以从这个方向去考虑下。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: JavaSocket设置timeout的几种常用方式说明

本文链接: https://www.lsjlt.com/news/171113.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaSocket设置timeout的几种常用方式说明
    目录1. Socket timeout1.1 建立连接connect timeout1.2 读取数据so timeout1.3 小结2. 使用案例2.1 MySQL jdbc tim...
    99+
    2022-11-13
    Java Socket Socket设置timeout Java Socket设置timeout
  • 说说Java异步调用的几种方式
    目录一、通过创建新线程二、通过线程池三、通过@Async注解四、通过CompletableFuture日常开发中,会经常遇到说,前台调服务,然后触发一个比较耗时的异步服务,且不用等异...
    99+
    2024-04-02
  • recover三种方式的说明
    1 SQL>recover database; 该命令用来对所有数据文件进行恢复,只能使用保存在文件系统上的归档日志及在线日志。使用此类命令的前提是控制文件不可以是还原或重建得来的。 SQL>r...
    99+
    2024-04-02
  • 达梦数据库的几种模式及状态说明
    一、达梦数据库三种模式 达梦数据库支持 3 种数据库模式: Normal 模式、 Primary 模式和 Standby 模式。 1.1 Normal 模式 用户可以正常访问数据库,操作没有限制。 正常生成本地归档,但不发送实时归档...
    99+
    2023-09-09
    数据库 sql 服务器 DM 达梦数据库 Powered by 金山文档
  • js函数声明的方式有几种
    这篇文章主要介绍“js函数声明的方式有几种”,在日常操作中,相信很多人在js函数声明的方式有几种问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”js函数声明的方式有几种”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-20
  • python的几种常用安装包的方式
    使用自带的pip 打开windows命令行,不需要输入“python”或输入”python3”,而是直接输入以下指令。我们默认系统环境变量已经按照安装位置设置好。 一般安装之后默认是已经安装好了pip,我们可以直接使用: 对于...
    99+
    2023-01-31
    几种 安装包 常用
  • 常用的android加密方式有哪几种
    常用的Android加密方式有以下几种:1. 文件加密:通过对文件进行加密,确保文件内容的机密性,常见的文件加密算法有AES(Adv...
    99+
    2023-10-18
    android
  • vue-cli中设置publicPath的几种方式对比
    目录设置publicPath的几种方式对比publicPath打包设置vue.config.js publicPath "./" npm run build无效设...
    99+
    2024-04-02
  • idea设置JVM运行参数的几种方式
    目录方式一方式二方式三对JVM运行参数进行修改是JVM性能调优的重要手段,下面介绍在应用程序开发过程中JVM参数设置的几种方式。 方式一 java程序运行时指定 -Dproperty...
    99+
    2024-04-02
  • golang 切片的三种使用方式及区别的说明
    概念 切片(slice)是建立在数组之上的更方便,更灵活,更强大的数据结构。切片并不存储任何元素而只是对现有数组的引用。 三种方式及细节案例 ①定义一个切片,然后让切片去引用一个已经...
    99+
    2024-04-02
  • 云服务器有哪几种方式设置
    云服务器可以提供多种不同的操作方式来设置和管理云服务器。以下是一些常见的云服务器设置方式,您可以根据实际情况进行选择和设置: 自定义参数设置:您可以为云服务器添加自定义参数,以控制云服务器的各种功能和性能。您可以选择将数据存储在本地数据...
    99+
    2023-10-26
    几种 方式 服务器
  • Keycloak各种配置及API的使用说明
    目录1.创建client2.怎样拿到access token信息 2.1采用前端登录(例如angular应用)的情况2.2 使用keycloak API3.拿到用户role...
    99+
    2023-03-09
    Keycloak配置 API的使用 Keycloak各种配置
  • mysql复制表的几种常用方式总结
    目录mysql复制表的几种方式 1、复制表结构及数据到新表2、只复制表结构到新表3、复制旧表的数据到新表(假设两个表结构一样)4、复制旧表的数据到新表(假设两个表结构不一样)5、可以将表1结构复制到表26、可以...
    99+
    2023-04-10
    mysql复制表语句 mysql如何复制表 mysql数据表复制
  • golang post请求常用的几种方式小结
    post请求常用的几种方式,记录一下 func httpPost() { resp, err := http.Post("https://www.abcd123.top/...
    99+
    2024-04-02
  • JavaScript中常见的几种继承方式
    目录原型继承内存图分析盗用构造函数继承分析组合继承原型链继承寄生式继承寄生组合式继承原型继承 function Parent(name) { this.name = name }...
    99+
    2024-04-02
  • appium中常见的几种点击方式
    目录1、最常见的点击方式click()方法 2、手指轻敲屏幕操作tap()方法3、手指按下操作press()方法4、模拟手指长按操作long_press()方法首先从app...
    99+
    2024-04-02
  • adb连接设备的几种方式
    1、USB连接 前提条件: 一台已安装adb环境的电脑一台手机、一根可传输数据的线(数据线,非充电线) 连接步骤: 将手机上的开发者选项打开(一般是:设置 > 关于手机,然后点按版本号七次)进入开发者...
    99+
    2023-09-01
    android
  • golang中常用的几种编码解码方式
    当我们需要将一个编码格式转换成另一个编码格式时,就需要用到转码。在Go语言中,转码操作非常方便,可以使用内置的encoding包来快速完成转码操作。Go语言中的encoding包提供了许多常用的编码解码方式,例如JSON、XML、Base6...
    99+
    2023-05-14
  • Java中FileWriter类的常用方法说明
    FileWriter字符输出流 构造方法 public FileWriter(String fileName) throws IOException 根据给定的文件名构造一个 ...
    99+
    2024-04-02
  • IDEA打包的两种方式及注意事项说明
    目录方式一、build打包方式二:maven打包总结方式一、build打包 1、进入project structure 2、要选择启动类以及MANIFEST.MF选择src目录下即...
    99+
    2023-05-15
    IDEA打包 IDEA打包的方式 IDEA打包注意事项
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作