Java Socket设置timeout几种常用方式总结
原文链接:https://my.oschina.net/shipley/blog/715196
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之后,可以更好的处理一些网络服务的客户端和服务端,同时对排查一些问题也很有帮助。一般的成熟的网络服务和客户端都应该有这两个参数的配置方法,当使用遇到类似问题可以从这个方向去考虑下。
Java Socket设置timeout几种常用方式总结的更多相关文章
- java线程池和五种常用线程池的策略使用与解析
java线程池和五种常用线程池策略使用与解析 一.线程池 关于为什么要使用线程池久不赘述了,首先看一下java中作为线程池Executor底层实现类的ThredPoolExecutor的构造函数 pu ...
- java线程池与五种常用线程池策略使用与解析
背景:面试中会要求对5中线程池作分析.所以要熟知线程池的运行细节,如CachedThreadPool会引发oom吗? java线程池与五种常用线程池策略使用与解析 可选择的阻塞队列BlockingQu ...
- Windows校验文件哈希hash的两种常用方式
大家经常都到哪儿去下载软件和应用程序呢?有没想过下载回来的软件.应用程序或资源是否安全呢?在 Windows 10 和 Office 2016 发布当初,很多没权限的朋友都使用第三方网站去下载安装映像 ...
- Postman几种常用方式
Postman几种常用方式 1.get请求直接拼URL形式 对于http接口,有get和post两种请求方式,当接口说明中未明确post中入参必须是json串时,均可用url方式请求 参数既可以写到U ...
- 【转载】Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式…)介绍
转载地址:http://blog.csdn.net/truong/article/details/46711045 关键字:Redis的Java客户端Jedis的八种调用方式(事务.管道.分布式…)介 ...
- sqlalchemy 转json 的几种常用方式
sqlalchemy 转json 的几种常用方式 # -*- coding:utf-8 -*- import datetime from flask import Flask, json, jsoni ...
- iOS- 网络访问两种常用方式【GET & POST】实现的几个主要步骤
1.前言 上次,在博客里谈谈了[GET & POST]的区别,这次准备主要是分享一下自己对[GET & POST]的理解和实现的主要步骤. 在这就不多废话了,直接进主题,有什么不足的欢 ...
- iOS- 网络请求的两种常用方式【GET & POST】的区别
GET和POST 网络请求的两种常用方式的实现[GET & POST] –GET的语义是获取指定URL上的资源 –将数据按照variable=value的形式,添加到action所指向的URL ...
- 【方法整理】Oracle 获取trace跟踪文件名的几种常用方式
[方法整理]Oracle 获取trace跟踪文件名的几种常用方式 1 BLOG文档结构图 2 前言部分 2.1 导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学 ...
- socket通信的三种实现方式
三种 socket 的实现方式 nodejs 下的 socket 服务端代码 const net = require('net') const server = net.createServer() ...
随机推荐
- [转帖]两种Nginx日志切分方案,狼厂主要在用第1种
两种Nginx日志切分方案,狼厂主要在用第1种 nginx的日志切分问题一直是运维nginx时需要重点关注的.本文将简单说明下nginx支持的两种日志切分方式. 一.定时任务切分 所谓的定时任务切分, ...
- [转帖]TLS 加速技术:Intel QuickAssist Technology(QAT)解决方案
https://zhuanlan.zhihu.com/p/631184323 3 人赞同了该文章 作者:vivo 互联网服务器团队- Ye Feng 本文介绍了 Intel QAT 技术方案,通过 ...
- [转帖]SCSI、ISCSI、iSER、NVMe、NVMe-oF、NVMe-oF over RDMA
在存储系统中,上层协议可以泛指"指令",也就是比如"读出从某某开始的多少长度的扇区",指令包含三大关键信息: (1)操作码:Opreation Code,或称为 ...
- [转帖]拯救关键业务上线:DBA 的惊魂24小时
一个电话,打破深夜的宁静 9月20日晚上10点 刚完成外地一个重点项目为期2周的现场支持,从机场回家的路上,一阵急促的铃声惊醒了出租车上昏昏欲睡的我,多年的工作经验告诉我这么晚来电一定是出事了,接起电 ...
- 【转帖】FIO磁盘性能测试工具
https://www.jianshu.com/p/70b8c7d5d217 FIO工具介绍 FIO 工具是一款用于测试硬件存储性能的辅助工具,兼具灵活性.可靠性从而从众多性能测试工具中脱颖而出.磁盘 ...
- Nginx调优总结-第六部分编译优化与简单测试
第六部分 编译优化 Nginx可以自行编译,所以里面可以设置多个编译策略. 也可以自行修改源码,便于比如进行ip_hash的全IP地址验证. 也可以修改nginx的版本号等信息, 避免内发现. 还可以 ...
- 【JS 逆向百例】某空气质量监测平台无限 debugger 以及数据动态加密
关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...
- P9779_[HUSTFC 2023] 不定项选择题_题解
rt 题目 有一道共 n 个选项的不定项选择题,它的答案至少包含一个选项,由于题目与选项的内容晦涩难懂,你打算通过尝试每一种可能的答案来通过这道题. 初始时所有选项都没有被勾选,你可以执行任意次下述操 ...
- Elasticsearch Relevance Engine---为AI变革提供高级搜索能力[ES向量搜索、常用配置参数、聚合功能等详解]
Elasticsearch Relevance Engine---为AI变革提供高级搜索能力[ES向量搜索.常用配置参数.聚合功能等详解] 今天要介绍的 Elasticsearch Relevance ...
- NLP涉及技术原理和应用简单讲解【一】:paddle(梯度裁剪、ONNX协议、动态图转静态图、推理部署)
参考链接: https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/advanced/gradient_clip_cn.html 1. ...