我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java Socket的超时浅析是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java Socket的超时浅析是什么

这篇文章将为大家详细讲解有关Java Socket的超时浅析是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

套接字或插座(socket)是一种软件形式的抽象,用于表达两台机器间一个连接的“终端”。针对一个特定的连接,每台机器上都有一个“套接字”,可以想象它们之间有一条虚拟的“线缆”。JAVA 有两个基于数据流的套接字类:ServerSocket,服务器用它“侦听”进入的连接;Socket,客户端用它初始一次连接。侦听套接字只能接收新的连接请求,不能接收实际的数据包。

套接字是基于TCP/IP实现的,它是用来提供一个访问TCP的服务接口,或者说套接字socket是TCP的应用编程接口API,通过它应用层就可以访问TCP提供的服务。

在JAVA中,我们用 ServerSocket、Socket类创建一个套接字连接,从套接字得到的结果是一个InputStream以及OutputStream对象,以便将连接作为一个IO流对象对待。通过IO流可以从流中读取数据或者写数据到流中,读写IO流会有异常IOException产生。

套接字底层是基于TCP的,所以socket的超时和TCP超时是相同的。下面先讨论套接字读写缓冲区,接着讨论连接建立超时、读写超时以及JAVA套接字编程的嵌套异常捕获和一个超时例子程序的抓包示例。

1、socket读写缓冲区

一旦创建了一个套接字实例,操作系统就会为其分配缓冲区以存放接收和要发送的数据。

Java Socket的超时浅析是什么

JAVA可以设置读写缓冲区的大小-setReceiveBufferSize(int size), setSendBufferSize(int size)。

向输出流写数据并不意味着数据实际上已经被发送,它们只是被复制到了发送缓冲区队列SendQ,就是在Socket的OutputStream上调用 flush()方法,也不能保证数据能够立即发送到网络。真正的数据发送是由操作系统的TCP协议栈模块从缓冲区中取数据发送到网络来完成的。

当有数据从网络来到时,TCP协议栈模块接收数据并放入接收缓冲区队列RecvQ,输入流InputStream通过read方法从RecvQ中取出数据。

2、socket连接建立超时

socket连接建立是基于TCP的连接建立过程。TCP的连接需要通过3次握手报文来完成,开始建立TCP连接时需要发送同步SYN报文,然后等待确认报文SYN+ACK,***再发送确认报文ACK。TCP连接的关闭通过4次挥手来完成,主动关闭TCP连接的一方发送FIN报文,等待对方的确认报文;被动关闭的一方也发送FIN报文,然等待确认报文。

Java Socket的超时浅析是什么

正在等待TCP连接请求的一端有一个固定长度的连接队列,该队列中的连接已经被TCP接受(即三次握手已经完成),但还没有被应用层所接受。TCP接受一个连接是将其放入这个连接队列,而应用层接受连接是将其从该队列中移出。应用层可以通过设置backlog变量来指明该连接队列的***长度,即已被TCP接受而等待应用层接受的***连接数。

当一个连接请求SYN到达时,TCP确定是否接受这个连接。如果队列中还有空间,TCP模块将对SYN进行确认并完成连接的建立。但应用层只有在三次握手中的第三个报文收到后才会知道这个新连接。如果队列没有空间,TCP将不理会收到的SYN。

如果应用层不能及时接受已被TCP接受的连接,这些连接可能占满整个连接队列,新的连接请求可能不被响应而会超时。如果一个连接请求SYN发送后,一段时间后没有收到确认SYN+ACK,TCP会重传这个连接请求SYN两次,每次重传的时间间隔加倍,在规定的时间内仍没有收到SYN+ACK,TCP将放弃这个连接请求,连接建立就超时了。

JAVA Socket连接建立超时和TCP是相同的,如果TCP建立连接时三次握手超时,那么导致Socket连接建立也就超时了。可以设置Socket连接建立的超时时间-

connect(SocketAddress endpoint, int timeout)

如果在timeout内,连接没有建立成功,在TimeoutException异常被抛出。如果timeout的值小于三次握手的时间,那么Socket连接永远也不会建立。

不同的应用层有不同的连接建立过程,Socket的连接建立和TCP一样-仅仅需要三次握手就完成连接,但有些应用程序需要交互很多信息后才能成功建立连接,比如Telnet协议,在TCP三次握手完成后,需要进行选项协商之后,Telnet连接才建立完成。

3、socket读超时

如果输入缓冲队列RecvQ中没有数据,read操作会一直阻塞而挂起线程,直到有新的数据到来或者有异常产生。调用setSoTimeout(int timeout)可以设置超时时间,如果到了超时时间仍没有数据,read会抛出一个SocketTimeoutException,程序需要捕获这个异常,但是当前的socket连接仍然是有效的。

如果对方进程崩溃、对方机器突然重启、网络断开,本端的read会一直阻塞下去,这时设置超时时间是非常重要的,否则调用read的线程会一直挂起。

TCP模块把接收到的数据放入RecvQ中,直到应用层调用输入流的read方法来读取。如果RecvQ队列被填满了,这时TCP会根据滑动窗口机制通知对方不要继续发送数据,本端停止接收从对端发送来的数据,直到接收者应用程序调用输入流的read方法后腾出了空间。

4、socket写超时

socket的写超时是基于TCP的超时重传。超时重传是TCP保证数据可靠性传输的一个重要机制,其原理是在发送一个数据报文后就开启一个计时器,在一定时间内如果没有得到发送报文的确认ACK,那么就重新发送报文。如果重新发送多次之后,仍没有确认报文,就发送一个复位报文RST,然后关闭TCP连接。***数据报文发送与复位报文传输之间的时间差大约为9分钟,也就是说如果9分钟内没有得到确认报文,就关闭连接。但是这个值是根据不同的TCP协议栈实现而不同。

如果发送端调用write持续地写出数据,直到SendQ队列被填满。如果在SendQ队列已满时调用write方法,则write将被阻塞,直到 SendQ有新的空闲空间为止,也就是说直到一些字节传输到了接收者套接字的RecvQ中。如果此时RecvQ队列也已经被填满,所有操作都将停止,直到接收端调用read方法将一些字节传输到应用程序。

当Socket的write发送数据时,如果网线断开、对端进程崩溃或者对端机器重启动,TCP模块会重传数据,***超时而关闭连接。下次如再调用write会导致一个异常而退出。

Socket写超时是基于TCP协议栈的超时重传机制,一般不需要设置write的超时时间,也没有提供这种方法。

5、双重嵌套异常捕获

如果ServerSocket、Socket构造失败,只需要仅仅捕获这个构造失败异常而不需要调用套接字的close方法来释放资源(必须保证构造失败后不会留下任何需要清除的资源),因为这时套接字内部资源没有被成功分配。如果构造成功,必须进入一个try finally语句块里调用close释放套接字。请参照下面例子程序。

import java.net.*;  import java.io.*;  public class SocketClientTest  {    public static final int PORT = 8088;    public static void main( String[] args ) throws Exception    {      InetAddress addr = InetAddress.getByName( "127.0.0.1" );      Socket socket = new Socket();      try     {        socket.connect( new InetSocketAddress( addr, PORT ), 30000 );        socket.setSendBufferSize(100);                BufferedWriter out = new BufferedWriter( new OutputStreamWriter( socket.getOutputStream() ) );        int i = 0;                while( true )        {          System.out.println( "client sent --- hello *** " + i++ );          out.write( "client sent --- hello *** " + i );          out.flush();                    Thread.sleep( 1000 );        }      }      finally     {        socket.close();      }    }  }
import java.io.*;  import java.net.ServerSocket;  import java.net.Socket;  public class SocketServerTest  {    public static final int PORT = 8088;    public static final int BACKLOG = 2;    public static void main( String[] args ) throws IOException    {      ServerSocket server = new ServerSocket( PORT, BACKLOG );      System.out.println("started: " + server);      try     {        Socket socket = server.accept();        try       {          BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );          String info = null;                    while( ( info = in.readLine() ) != null )          {            System.out.println( info );          }        }        finally       {          socket.close();        }      }      finally     {        server.close();      }    }  }

执行上面的程序,在程序运行一会儿之后,断开client和server之间的网络连接,在机器上输出如下:

Server上的输出:

Echoing:client sent -----hello0Echoing:client sent -----hello1Echoing:client sent -----hello2Echoing:client sent -----hello3Echoing:client sent -----hello4Echoing:client sent -----hello5Echoing:client sent -----hello6

---->> 断开了网络连接之后没有数据输出

Client上的输出:

socket default timeout = 0socket = Socket[addr=/10.15.9.99,port=8088,localport=4691]begin to readclient sent --- hello *** 0client sent --- hello *** 1client sent --- hello *** 2client sent --- hello *** 3client sent --- hello *** 4client sent --- hello *** 5client sent --- hello *** 6client sent --- hello *** 7client sent --- hello *** 8 client sent --- hello *** 9client sent --- hello *** 10

---->> 断开网络连接后客户端进程挂起

java.net.SocketException : Connection reset by peer: socket write error       at java.net.SocketOutputStream.socketWrite0( Native Method )       at java.net.SocketOutputStream.socketWrite( SocketOutputStream.java:92 )       at java.net.SocketOutputStream.write( SocketOutputStream.java:136 )       at sun.nio.cs.StreamEncoder.writeBytes( StreamEncoder.java:202 )       at sun.nio.cs.StreamEncoder.implFlushBuffer( StreamEncoder.java:272 )       at sun.nio.cs.StreamEncoder.implFlush( StreamEncoder.java:276 )       at sun.nio.cs.StreamEncoder.flush( StreamEncoder.java:122 )       at java.io.OutputStreamWriter.flush( OutputStreamWriter.java:212 )       at java.io.BufferedWriter.flush( BufferedWriter.java:236 )       at com.xtera.view.SocketClientTest.main( SocketClientTest.java:99 )

当hello6被发送到server端后,网络连接被断开,这时server端不能接收任何数据而挂起。client端仍然继续发送数据,实际上hello7、hello8、hello9、hello10都被复制到SendQ队列中,write方法立即返回。当client的SendQ队列被填满之后,write方法就被阻塞。TCP模块在发送报文hello7之后,没有收到确认而超时重传,再重传几次之后关闭了TCP连接,同时导致被阻塞的write方法异常返回。

通过抓包工具,我们可以看到超时重传的报文。

Java Socket的超时浅析是什么

Java Socket的超时浅析是什么

关于Java Socket的超时浅析是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java Socket的超时浅析是什么

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java Socket的超时浅析是什么

这篇文章将为大家详细讲解有关Java Socket的超时浅析是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。套接字或插座(socket)是一种软件形式的抽象,用于表达两台机器间一个连接的
2023-06-17

Java中的Socket用法是什么

Java中的Socket用法是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1 问题引入1.1 网络架构模型网络架构模型主要有OSI参考模型和TCP/IP五层模型1.1.1
2023-06-22

Java中socket通信的原理是什么

Java中socket通信的原理是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。java.net.Socket继承于java.lang.Object,有八个
2023-06-17

Java NIO Socket通信的方法是什么

这篇文章主要讲解了“Java NIO Socket通信的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java NIO Socket通信的方法是什么”吧!服务器代码:import
2023-06-17

Java的深浅拷贝是什么

本篇内容介绍了“Java的深浅拷贝是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!引用拷贝引用拷贝会生成一个新的对象引用地址,但是两个最
2023-06-15

Java Socket线程的设计原理是什么

这篇文章主要讲解了“Java Socket线程的设计原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java Socket线程的设计原理是什么”吧!Java Socket线程我们经常
2023-06-17

Java socket通信与C++之间的关系是什么

Java socket通信与C++之间的关系是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。c++builer与Java socket通信是我们在编程中经常用到的,有不少的
2023-06-17

浅谈Java中的this作为返回值时返回的是什么

有时会遇到this作为返回值的情况,那么此时返回的到底是什么呢?返回的是调用this所处方法的那个对象的引用,读起来有点绕口哈,有没有想起小学语文分析句子成份的试题,哈哈。一点点分析的话,主干是“返回的是引用”;什么引用呢?“那个对象的引用
2023-05-30

TCP的超时与重传机制是什么

这篇文章主要介绍“TCP的超时与重传机制是什么”,在日常操作中,相信很多人在TCP的超时与重传机制是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”TCP的超时与重传机制是什么”的疑惑有所帮助!接下来,请跟
2023-06-27

mysql连接超时设置的方法是什么

在MySQL中,可以通过修改wait_timeout参数来设置连接的超时时间。wait_timeout参数表示在没有活动连接的情况下,服务器将断开连接之前等待的时间(以秒为单位)。默认值为28800秒(8小时)。要修改wait_timeo
mysql连接超时设置的方法是什么
2024-04-09

Java Socket编程中对于run的使用方法是什么

Java Socket编程中对于run的使用方法是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Java Socket编程在使用的时候有很多语句需要我们注意,其中run
2023-06-17

B2C会远超越C2C的原因分析是什么

B2C会远超越C2C的原因分析是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。我一直看好B2C,不太看好C2C。我不会高谈阔论,简单解释下我的观点,都是基于基本的逻辑。
2023-06-12

java中的时间API是什么

这篇文章主要介绍“java中的时间API是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“java中的时间API是什么”文章能帮助大家解决问题。1、Clock类可用于访问当前日期和时间。Clock
2023-06-30

连接服务器超时指的是什么意思

连接服务器超时指的是:在程序默认的等待时间内没有得到服务器的响应。连接服务器超时的原因1、网络断开,不过经常显示无法连接。网络阻塞,导致你不能在程序默认等待时间内得到回复数据包。2、网络不稳定,网络无法完整传送服务器信息、系统问题,系统资源
2023-02-15

Java类的加载时机是什么时候

本篇内容主要讲解“Java类的加载时机是什么时候”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java类的加载时机是什么时候”吧!必须初始化的四种情况有四种情况类是必须要进行初始化的,对于这四种
2023-06-25

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录