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

简介: 本文为原创,如需转载,请注明作者和出处,谢谢! 上一篇:Java网络编程从入门到精通(15):为什么要使用SocketAddress来管理网络地址    客户端套接字的超时(timeout)就是指在客户端通过Socket和服务器进行通讯的过程中,由于网络延迟,网络阻塞等原因,造成服务器并未及时响应客户端的一种现象。

本文为原创,如需转载,请注明作者和出处,谢谢!

上一篇:Java网络编程从入门到精通(15):为什么要使用SocketAddress来管理网络地址

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

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

下一篇:
Java网络编程从入门到精通(17):Socket类的getter和setter方法(1)



国内最棒的Google Android技术社区(eoeandroid),欢迎访问!

《银河系列原创教程》发布

《Java Web开发速学宝典》出版,欢迎定购

目录
相关文章
|
9月前
|
JSON 移动开发 网络协议
Java网络编程:Socket通信与HTTP客户端
本文全面讲解Java网络编程,涵盖TCP与UDP协议区别、Socket编程、HTTP客户端开发及实战案例,助你掌握实时通信、文件传输、聊天应用等场景,附性能优化与面试高频问题解析。
|
7月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
373 1
|
7月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
350 1
|
11月前
|
JSON 中间件 Go
Go 网络编程:HTTP服务与客户端开发
Go 语言的 `net/http` 包功能强大,可快速构建高并发 HTTP 服务。本文从创建简单 HTTP 服务入手,逐步讲解请求与响应对象、URL 参数处理、自定义路由、JSON 接口、静态文件服务、中间件编写及 HTTPS 配置等内容。通过示例代码展示如何使用 `http.HandleFunc`、`http.ServeMux`、`http.Client` 等工具实现常见功能,帮助开发者掌握构建高效 Web 应用的核心技能。
521 61
|
11月前
|
运维 网络协议 Go
Go网络编程:基于TCP的网络服务端与客户端
本文介绍了使用 Go 语言的 `net` 包开发 TCP 网络服务的基础与进阶内容。首先简述了 TCP 协议的基本概念和通信流程,接着详细讲解了服务端与客户端的开发步骤,并提供了简单回显服务的示例代码。同时,文章探讨了服务端并发处理连接的方法,以及粘包/拆包、异常检测、超时控制等进阶技巧。最后通过群聊服务端的实战案例巩固知识点,并总结了 TCP 在高可靠性场景中的优势及 Go 并发模型带来的便利性。
|
网络协议 开发者 Python
深度探索Python Socket编程:从理论到实践,进阶篇带你领略网络编程的魅力!
【7月更文挑战第25天】在网络编程中, Python Socket编程因灵活性强而广受青睐。本文采用问答形式深入探讨其进阶技巧。**问题一**: Socket编程基于TCP/IP,通过创建Socket对象实现通信,支持客户端和服务器间的数据交换。**问题二**: 提升并发处理能力的方法包括多线程(适用于I/O密集型任务)、多进程(绕过GIL限制)和异步IO(asyncio)。**问题三**: 提供了一个使用asyncio库实现的异步Socket服务器示例,展示如何接收及响应客户端消息。通过这些内容,希望能激发读者对网络编程的兴趣并引导进一步探索。
338 4
|
开发者 Python
Python Socket编程:不只是基础,更有进阶秘籍,让你的网络应用飞起来!
【7月更文挑战第25天】在网络应用蓬勃发展的数字时代,Python凭借其简洁的语法和强大的库支持成为开发高效应用的首选。本文通过实时聊天室案例,介绍了Python Socket编程的基础与进阶技巧,包括服务器与客户端的建立、数据交换等基础篇内容,以及使用多线程和异步IO提升性能的进阶篇。基础示例展示了服务器端监听连接请求、接收转发消息,客户端连接服务器并收发消息的过程。进阶部分讨论了如何利用Python的`threading`模块和`asyncio`库来处理多客户端连接,提高应用的并发处理能力和响应速度。掌握这些技能,能使开发者在网络编程领域更加游刃有余,构建出高性能的应用程序。
219 3
|
网络协议 测试技术 网络安全
Python编程-Socket网络编程
Python编程-Socket网络编程
252 0
|
网络协议 Python
网络世界的建筑师:Python Socket编程基础与进阶,构建你的网络帝国!
【7月更文挑战第26天】在网络的数字宇宙中,Python Socket编程是开启网络世界大门的钥匙。本指南将引领你从基础到实战,成为网络世界的建筑师。
306 2