Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 321|回复: 0

[网络编程学习]Java网络编程从入门到精通(16)客户端套接字的超时

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-11-5 00:03:46 | 显示全部楼层 |阅读模式
    客户端套接字的超时(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
      错误。这个抛出错误的时间和服务端程序的超时设置有关;也就是这个错误是由于服务端程序主动将客户端网络连接断开而产生的。

      
    本文出自 “软件改变整个宇宙” 博客,请务必保留此出处http://androidguy.blog.51cto.com/974126/214445



      
      
       
       

         
       

         
       
      
    复制代码

    源码下载:http://file.javaxxz.com/2014/11/5/000345781.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 13:41 , Processed in 0.389101 second(s), 48 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表