当前位置: 首页 > news >正文

Java网络编程从入门到精通(16):客户端套接字(Socket)的超时

客户端套接字的超时(timeout)就是指在客户端通过Socket和 服务器进行通讯的过程中,由于网络延迟,网络阻塞等原因,造成 服务器并未及时响应客户端的一种现象。在一段时间后,客户端由于未收到服务端的响应而抛出一个超时错误; 其中客户端所等待的时间就是超时时间。

由于生产超时错误的一端都是被动端;也就是说,这一端是在接收数据,而不是发送数据。对于客户端Socket来说,只有两个地方是在接收数据;一个是在连接服务器时;另一个是在连接服务器成功后,接收服务器发过来的数据时。因此,客户端超时也分为两种类型:连接超时和读取数据超时。

一、连接超时

这种超时在前面的例子中已经使用过。在Socket类中只有通过connect方法的第二个参数才能指定连接超时的时间。由于使用connect方法连接服务器必须要指定IP和端口;因此,无效的IP或端口将会引发连接超时错误。

二、读取数据超时

在连接服务器成功后,Socket所做的最重要的两件事就是“接收数据”和“发送数据”;而在接收数据时可能因为网络延迟、网络阻塞等原因,客户端一直处于等待状态;而客户端在等待一段时间后,如果服务器还没有发送数据到客户端,那么客户端Socket将会抛出一个超时错误。

我们可以通过Socket类的setSoTimeout方法来设置读取数据超时的时间;时间的单位是毫秒。这个方法必须在读取数据之前调用才会生效。如果将超时时间设为0,则不使用超时时间;也就是说,客户端什么时候和服务器断开,将完全取决于服务端程序的超时设置。如下面的语句将读取数据超时时间设为5秒。

Socket socket = new Socket();
socket.setSoTimeout(
5000);
socket.connect(… …);
socket.getInputStream().read();

要注意的是不要将设置连接超时和读取数据超时设置得太小,如果值太小,如100,可能会造成服务器的数据还没来得及发过来,客户端就抛出超时错误的现象。下面的代码给出了一个用于测试连接超时和读取数据超时的例子。

package mynet;

import java.net.*;

public class SocketTimeout
{
public static void main(String[] args)
{
long time1 = 0, time2 = 0;
Socket socket
= new Socket();
try
{
if (args.length < 4)
{
System.out.println(
"参数错误!");
return;
}

time1
= System.currentTimeMillis();
socket.connect(
new InetSocketAddress(args[0], Integer
.parseInt(args[
1])), Integer.parseInt(args[2]));
socket.setSoTimeout(Integer.parseInt(args[
3]));
time1
= System.currentTimeMillis();
socket.getInputStream().read();
}
catch (SocketTimeoutException e)
{
if (!socket.isClosed() && socket.isConnected())
System.out.println(
"读取数据超时!");
else
System.out.println(
"连接超时");
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
finally
{
time2
= System.currentTimeMillis();
System.out.println(time2
- time1);
}
}
}

SocketTimeout类的main方法需要4个参数:IP(域名)、端口、连接超时、读取数据超时。下面让我们来用一组数据来测试这个例子。

测试1 :无效IP引发的超时错误

执行如下命令:

java mynet.SocketTimeout 192.168.18.24 80 3000 5000

运行结果:

连接超时
3045

注意:192.168.18.24是一个无效的IP;如果这个IP在网络环境中存在,请换其它的无效的IP.在这个测试用例中不能将无效的IP换成无效的域名;这是因为如果使用了域名来连接服务器,Java会先通过DNS将域名映射成相应的IP;如果这个域名是无效的,在映射的过程中就会出错;因此,程序也就不会执行连接服务器操作,自然也就不会抛出“连接超时”错误了。

测试2 :无效端口引发的超时错误

执行如下命令:

java mynet.SocketTimeout www.ptpress.com.cn 8888 3000 5000

运行结果:

连接超时
3075

测试3 :读取数据超时错误

执行如下命令:

java mynet.SocketTimeout www.ptpress.com.cn 80 3000 5000

运行结果:

读取数据超时!
5008

测试4 :将读取数据超时设为0的效果

执行如下命令:

java mynet.SocketTimeout www.ptpress.com.cn 80 3000 0

运行结果:

Connection reset
131519

从前3个测试的输出结果不难看出,每个测试用例都将连接超时和读取数据超时分别设为3000和5000毫秒;而它们的运行结果并不是3000和5000毫秒,而是在所设定的超时时间的左右摇摆;这主要是因为系统所输出的时间并不都是超时时间;如有一些时间是Java处理错误、向控制台输出信息的时间。另外,由于系统计时的误差,也会影响到超时时间的准确性。但不管怎样,超时时间总会在所设定的时间周围摇摆。

对于测试4,将读取数据超时设为0后,SocketTimeout类经过了2分多钟(131519毫秒)才抛出Connection reset错误。这个抛出错误的时间和服务端程序的超时设置有关;也就是这个错误是由于服务端程序主动将客户端网络连接断开而产生的。

相关文章:

  • 2020牛客暑期多校第十场 C - Decrement on the Tree(树的思维好题)
  • 页面校验用通用js
  • SPOJ - FIBOSUM Fibonacci Sum(递推公式/矩阵快速幂)
  • 保证唯一性只能靠建唯一索引
  • HDU - 6860 Fluctuation Limit(双向贪心/思维)
  • 付出就有回报,坚持才会胜利
  • 2020牛客暑期多校第九场 E - Groundhog Chasing Death(gcd+质因数分解)
  • 高中毕业从事研发,我应该继续提高学历吗?——网上答疑(33)
  • 2020牛客暑期多校第九场 F- Groundhog Looking Dowdy(尺取)
  • HDU - 6863 Isomorphic Strings(因数分解+字符串技巧)
  • 高中毕业从事研发,我应该继续提高学历吗?——网上答疑(3
  • 2020牛客暑期多校第九场 K - The Flee Plan of Groundhog(思维+dfs)
  • iPhone人机界面指南中的意见和建议摘录
  • 2020牛客暑期多校第九场 A - Groundhog and 2-Power Representation(栈/pyhton)
  • 投稿的事情
  • Apache Spark Streaming 使用实例
  • CentOS从零开始部署Nodejs项目
  • IP路由与转发
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • rabbitmq延迟消息示例
  • scrapy学习之路4(itemloder的使用)
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 程序员最讨厌的9句话,你可有补充?
  • 官方解决所有 npm 全局安装权限问题
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 排序(1):冒泡排序
  • 新版博客前端前瞻
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • $$$$GB2312-80区位编码表$$$$
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (C语言)字符分类函数
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (十一)c52学习之旅-动态数码管
  • (一)基于IDEA的JAVA基础12
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .net 7 上传文件踩坑
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .NET中使用Redis (二)
  • @configuration注解_2w字长文给你讲透了配置类为什么要添加 @Configuration注解
  • @font-face 用字体画图标
  • @软考考生,这份软考高分攻略你须知道
  • [1181]linux两台服务器之间传输文件和文件夹
  • [2016.7.Test1] T1 三进制异或
  • [ai笔记3] ai春晚观后感-谈谈ai与艺术
  • [BZOJ] 1001: [BeiJing2006]狼抓兔子
  • [C# 基础知识系列]专题十六:Linq介绍
  • [C++] new和delete