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 (域名)、端口、连接超时、读取数据超时。下面让我们来用一组数据来测试这个例子。
测试 :无效 IP 引发的超时错误
执行如下命令:
java mynet.SocketTimeout  192.168 . 18.24   80   3000   5000
运行结果:
连接超时
3045
注意:192.168.18.24是一个无效的IP;如果这个IP在网络环境中存在,请换其它的无效的IP。在这个测试用例中不能将无效的IP换成无效的域名;这是因为如果使用了域名来连接服务器,Java会先通过DNS将域名映射成相应的IP;如果这个域名是无效的,在映射的过程中就会出错;因此,程序也就不会执行连接服务器操作,自然也就不会抛出“连接超时”错误了。
测试 :无效端口引发的超时错误
执行如下命令:
java mynet.SocketTimeout  www.ptpress.com.cn  8888   3000   5000
运行结果:
连接超时
3075
测试 :读取数据超时错误
执行如下命令:
java mynet.SocketTimeout www.ptpress.com.cn  80   3000   5000
运行结果:
读取数据超时 !
5008
测试 :将读取数据超时设为 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 错误。这个抛出错误的时间和服务端程序的超时设置有关;也就是这个错误是由于服务端程序主动将客户端网络连接断开而产生的。




本文转自 androidguy 51CTO博客,原文链接:http://blog.51cto.com/androidguy/214445,如需转载请自行联系原作者

相关文章
|
30天前
|
人工智能 Java API
MCP客户端调用看这一篇就够了(Java版)
本文详细介绍了MCP(Model Context Protocol)客户端的开发方法,包括在没有MCP时的痛点、MCP的作用以及如何通过Spring-AI框架和原生SDK调用MCP服务。文章首先分析了MCP协议的必要性,接着分别讲解了Spring-AI框架和自研SDK的使用方式,涵盖配置LLM接口、工具注入、动态封装工具等步骤,并提供了代码示例。此外,还记录了开发过程中遇到的问题及解决办法,如版本冲突、服务连接超时等。最后,文章探讨了框架与原生SDK的选择,认为框架适合快速构建应用,而原生SDK更适合平台级开发,强调了两者结合使用的价值。
1758 27
MCP客户端调用看这一篇就够了(Java版)
|
1月前
|
存储 网络协议 Java
Java获取客户端IP问题:返回127.0.0.1
总结:要解决Java获取客户端IP返回127.0.0.1的问题,首先要找出原因,再采取合适的解决方案。请参考上述方案来改进代码,确保在各种网络环境下都能正确获取客户端IP地址。希望本文对您有所帮助。
140 25
|
3月前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
145 23
|
4月前
|
监控 Linux PHP
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
132 20
|
4月前
|
安全 网络协议 Java
Java网络编程封装
Java网络编程封装原理旨在隐藏底层通信细节,提供简洁、安全的高层接口。通过简化开发、提高安全性和增强可维护性,封装使开发者能更高效地进行网络应用开发。常见的封装层次包括套接字层(如Socket和ServerSocket类),以及更高层次的HTTP请求封装(如RestTemplate)。示例代码展示了如何使用RestTemplate简化HTTP请求的发送与处理,确保代码清晰易维护。
|
4月前
|
监控 关系型数据库 MySQL
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
77 0
|
7月前
|
网络协议 Java 物联网
Java网络编程知识点
Java网络编程知识点
117 13
|
7月前
|
存储 Java API
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
574 4
|
存储 自然语言处理 Java
Elasticsearch: java客户端之AdminClient
Elasticsearch: java客户端之AdminClient
Elasticsearch: java客户端之AdminClient
|
存储 自然语言处理 Java
Elasticsearch: java客户端之AdminClient
Elasticsearch: java客户端之AdminClient