深入分析Java I/O的工作机制 (三)网络I/O的工作机制 很详细

3.网络I/O的工作机制

前言:数据从一台主机(服务端)发送到网络中的另一台主机(客户端)需要经过很多步骤:首先需要有相互沟通的意向。其次要有能够沟通的物理渠道(物理链路):是通过电话,还是直接面对面交流。再次,双方见面时语言要能够交流,而且双方说话步调要一致,明白什么时候该自己说话,什么时候该对方说话(通信协议)。所以下面要讲一下通信协议和如何完成数据传输。  

什么是通信协议:通信协议其实就是一种规则和约定。就是两者想要交流必须要知道那种方式交流,什么时候去交流,交流什么内容,这就是通信协议。

什么是socket:socket就是网络中的一个端口,两个程序想要进行数据交互,至少要有一个socket(端口),http协议可以比作一个轿车,而socket可以比作是轿车的发动机,作用是比较重要的。

什么是SYN:是TCP和IP建立连接的一个握手信号。     当客户端和服务端建立正常的TCP网络连接时,  首先客户端会先向服务端发送一个SYN,  然后服务端会使用SYN+ACK接收这个消息, 然后客户端接收到服务器端的SYN+ACK最后客户端在使用ACK接收响应。

什么是ACK:ACK是一个确认字符,确认发过来的数据接收无误。     可以理解SYN是TCP和IP之间发送消息要使用的,可以理解ACK是TCP和IP之间接收响应要使用的。

什么是FIN: FIN可以说是用来关闭连接的。

什么是IP: IP就是你电脑的IP地址,当你和TCP通信是TCP需要知道通信的IP。

3.1.TCP状态转化  (TCP就是一个面向连接的,基于字节流的传输层通信协议)

先看一下如何建立和关闭一个TCP连接,TCP状态转换图(这个图太难画就不画了,这个图和书上的图意思一样。):

图解:  

  closed(CLOSED):是TCP状态转换的起始点,在连接超时或者连接关闭时会进入此状态。   为什么closed是起始点呢,因为一开始不可能你就处于连接的状态,在没连接的状态或超时状态就是进入closed,等你连接时就会走listen的状态。

  listen(LISTEN):服务端在等待连接时的状态,当服务端调用socket,bind,listen函数,会进入此状态,此状态是被动打开的,也就是客户端连接时进入此状态。

  syn-sent(SYN-SENT):这个状态是由closed主动打开的,当客户端发送syn给服务端,服务端不能正确连接,则直接进入closed状态。

  syn-rcvd(SYN-RCVD):服务端接收客户端的syn请求,服务端由listen状态进入该状态。同时服务端要回应一个ack,发送一个syn给客户端;另一种状态是:客户端在发送syn的同时接收到了服务端的syn请求,客户端会由syn-sent转换到该状态。

  established(ESTABLISHED):服务器端和客户端完成3次握手后进入该状态,说明已经可以传输数据了。

  fin-wait_1(FIN-WAIT_1):主动关闭的一方,由established状态进入此状态。具体动作是发送fin(关闭连接)给对方。

  fin-wait_2(FIN-WAIT_2):主动关闭的一方,接收到对方的fin  ack(关闭连接和响应),进入此状态。由此不能再接收对方的数据,但是能够向对方发送数据。

  close-wait(CLOSE-WAIT):接收到fin以后,被动关闭(被动关闭连接)的一方进入此状态。具体动作是在接收到fin的同时发生ack。

  last-ack(LAST-ACK):被动关闭(被动关闭连接)的一方,发起关闭请求,由close-wait状态进入此状态。具体动作是发生fin给对方,同时在接收到ack时进入closed状态(就是通信结束以后进入无连接的状态。)。

  closing(CLOSING):两边同时发起关闭请求时,会由fin-wait_1进入此状态,具体动作是接收到fin请求,同时响应一个ack。

  time-wait(TIME-WAIT):这个状态比较复杂,但也是我们最常见的一个连接状态,有三个状态可以转化为此状态。

      由fin-wait_2转换到time-wait,具体情况是:在双方不同时发起fin的情况下,主动关闭的一方在完成自身发起的关闭请求后,接收到被动关闭一方的fin后进入此状态。

      由closing转换到time-wait,具体情况是:在双方同时发起关闭,都做了发起fin的请求,同时接收到了fin并做了ack的情况下,这时就由closing状态进入time-wait状态。

      由fin-wait_1转换到time-wait,具体情况是:同时接收到fin(对方发起)和ack(本身发起的fin回应),它与closing转换到time-wait的区别在于本身发起的fin回应的ack先于对方的fin请求到达,而由closing转换到time-wait则是fin先到达。

3.2.影响网络传输的因素

将一份数据从一个地方正确的传输到另一个地方所需要的时间我们称之为响应时间,影响这个响应时间的因素有很多。

  1.网络带宽:带宽和宽带不一样,但是却差不多,这个带宽的速度回影响到响应时间的速度,一般平均网络带宽只有1.7Mb/s左右。

  2.传输距离:传输数据,也就是数据在光纤中要走的距离,光的传播速度很快,但也是有时间的,而且光纤不是直线走的,也有折射率,而且传输也有传输延迟这种问题。

  3.TCP拥塞控制:TCP传输是一个“停-等-停-等”的协议,传输方和接受方的步调要一致,要达到步调一致就要通过拥塞控制来调节。TCP在传输时会设定一个窗口,这个窗口的大小是由带宽和RTT决定的。计算的公式是带宽xRTT。通过这个值可以得出理论上最优的TCP缓冲区的大小。

3.3.Java Socket的工作机制

  socket这个概念没有对应到一个具体的实体,它描述计算机之间完成相互通信的一种抽象功能。打个比方,可以把socket比作两个城市之间的交通工具,有了它,就可以在城市之间来回穿梭了。交通工具有多种,每种交通工具也有相应的交通规则。socket也一样,也有多种。大部分情况下我们使用的都是基于TCP/IP的流套接字,它是一种稳定的通信协议。

socket通信示例图:

主机A的应用程序要能和主机B的应用程序通信,必须通过Socket建立连接,而建立Socket连接必须由底层TCP/IP来建立。建立TCP需要底层IP来寻址网络中的主机。网络层使用的IP可以帮助我们根据IP地质来找到目标主机,但是在一台主机上可能运行着多个程序,如何才能与指定的应用程序通信就要通过TCP或UPD的地址也就是端口号来指定。这样就可以通过一个socket实例来唯一代表一个主机上的应用程序的通信链路了。

3.4.建立通信链路

当客户端要与服务端通信时,客户端首先要创建一个socket实例,操作系统将为这个socket实例分配一个没有被使用的本地端口号,并创建一个包含本地地址、远程地址和端口号的套接字数据结构,这个数据结构将一直保存在系统中知道这个连接关闭。在创建socket实例的构造函数正确返回之前,将要进行TCP的三次握手协议,TCP握手协议完成后,socket实例对象将创建完成,否则将抛出IOException错误。

与之对应的服务端将创建一个serverSocket实例,创建serverSocket比较简单,只要指定的端口号没有被占用,一般实例创建都会成功。同时操作系统也会为serverSocket实例创建一个底层数据结构,在这个数据结构中包含指定监听的端口号和包含监听地址的通配符,通常情况下都是“*”一个星号,即监听所有地址。之后当调用accept()方法时,将进入堵塞状态,等待客户端的请求。当一个新的请求到来时,将为这个连接创建一个新的套接字数据结构,改套接字数据的信息包含的地址和端口信息正是请求源地址和端口。这个新创建的数据结构将会关联到serverSocket实例的一个未完成的连接数据结构列表中。注意,这时服务端的与之对应的socket实例并没有完成创建,而要等到与客户端的3此握手完成后,这个服务端的socket实例才会返回,并将这个socket实例对应的数据结构从未完成列表中移到已完成列表中。所以与serverSocket所关联的列表中每个数据结构都代表与一个客户端建立的TCP连接。

3.5数据传输

传输数据是我们建立连接的主要目的,下面说一下如何通过socket传输数据。

当连接已经建立成功时,服务端和客户端都会拥有一个socket实例,每个socket实例都有一个inputStream和OutPutStream,并通过这两个对象来交互数据,同时我们也知道网络I/O都是以字节流传输的,当创建SOcket对象时,操作系统将会为inputStream和outputStream分别分配一定大小的缓存区,数据的写入和读取都是通过这个缓存区完成的,写入端将数据写到outputStream对应的SendQ队列中,当队列填满时,数据将被转移到另一端InputStream的RecvQ队列中,如果这时RecvQ已经满了,nameOutputStream的write方法将会堵塞,直到RecvQ队列有足够的空间容纳SendQ发送的数据。特别值得注意的是,这个缓存区的大小及写入端的速度和读取端的速度非常影响这个链接的数据传输效率,由于可能会发送阻塞,所以网络I/O与磁盘I/O不同的是数据的写入和读取还要有一个协调的过程,如果在两边同时传送数据可能会产生死锁。

妈耶终于写完了,后面这些理论没做太多的深入,几天后再过一遍。

原文地址:https://www.cnblogs.com/java-263/p/10293847.html

时间: 2024-11-05 02:29:35

深入分析Java I/O的工作机制 (三)网络I/O的工作机制 很详细的相关文章

深入分析 Java I/O 的工作机制

I/O 问题可以说是当今互联网 Web 应用中所面临的主要问题之一,因为当前在这个海量数据时代,数据在网络中随处流动.这个流动的过程中都涉及到 I/O 问题,可以说大部分 Web 应用系统的瓶颈都是 I/O 瓶颈.本文的目的正是分析 I/O 的内在工作机制,你将了解到:Java 的 I/O 类库的基本架构:磁盘 I/O 工作机制:网络 I/O 的工作机制:其中以网络 I/O 为重点介绍 Java Socket 的工作方式:你还将了解到 NIO 的工作方式,还有同步和异步以及阻塞与非阻塞的区别,最

深入分析 Java I/O 的工作机制(转载)

声明:本文转自 http://www.ibm.com/developerworks/cn/java/j-lo-javaio/ I/O 问题可以说是当今互联网 Web 应用中所面临的主要问题之一,因为当前在这个海量数据时代,数据在网络中随处流动.这个流动的过程中都涉及到 I/O 问题,可以说大部分 Web 应用系统的瓶颈都是 I/O 瓶颈.本文的目的正是分析 I/O 的内在工作机制,你将了解到:Java 的 I/O 类库的基本架构:磁盘 I/O 工作机制:网络 I/O 的工作机制:其中以网络 I/

深入分析 Java I/O 的工作机制--转载

Java 的 I/O 类库的基本架构 I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道.在当今这个数据大爆炸时代,I/O 问题尤其突出,很容易成为一个性能瓶颈.正因如此,所以 Java 在 I/O 上也一直在做持续的优化,如从 1.4 开始引入了 NIO,提升了 I/O 的性能.关于 NIO 我们将在后面详细介绍. Java 的 I/O 操作类在包 java.io 下,大概有将近 80 个类,但是这些类大概可以

JVM(三):深入分析Java字节码-上

JVM(三):深入分析Java字节码-上 字节码文章分为上下两篇,上篇也就是本文主要讲述class文件存在的意义,以及其带来的益处.并分析其内在构成之一 ---字节码,而下篇则从指令集方面着手,讲解指令集都有哪些,以及其各自代表的含义.最后总结一下Class文件存在的必然性. 意义 前面说过 Java 虚拟机拥有平台无关性,但其实现在语言无关性在 JVM 和更加的体现了出来.表现就是目前越来越多的语言可以在 JVM 上运行,而这背后的逻辑,就是这些语言都会被编译为 Class 文件,然后在JVM

高级Java工程师必备 ----- 深入分析 Java IO (三)

概述 Java IO即Java 输入输出系统.不管我们编写何种应用,都难免和各种输入输出相关的媒介打交道,其实和媒介进行IO的过程是十分复杂的,这要考虑的因素特别多,比如我们要考虑和哪种媒介进行IO(文件.控制台.网络),我们还要考虑具体和它们的通信方式(顺序.随机.二进制.按字符.按字.按行等等).Java类库的设计者通过设计大量的类来攻克这些难题,这些类就位于java.io包中. 在JDK1.4之后,为了提高Java IO的效率,Java又提供了一套新的IO,Java New IO简称Jav

[转]深入分析 Java 中的中文编码问题

收益匪浅,所以转发至此 原文链接: http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 深入分析 Java 中的中文编码问题 编码问题一直困扰着开发人员,尤其在 Java 中更加明显,因为 Java 是跨平台语言,不同平台之间编码之间的切换较多.本文将向你详细介绍 Java 中编码问题出现的根本原因,你将了解到:Java 中经常遇到的几种编码格式的区别:Java 中经常需要编码的场景:出现中文问题的原因分析:在开发 Java

深入分析Java Web技术(1)

BS网络模型的基本过程: 当我们在浏览器中输入"www.google.com"的时候,首先会请求DNS服务器对域名进行解析成都应的IP地址,然后根据这个IP地址在互联网上找到谷歌的服务器,向这个服务器发送一个"get"请求,有这个服务器决定返回数据资源给请求的用户(在服务器端可能还会存在其他复杂的业务逻辑,服务器端有很多机器的话,需要考虑负载均衡,由哪一台服务器对资源进行回复,请求的文件是存储在静态文件中还是存储在分布式缓存中或者是数据库中,当数据返回服务器时,会发

深入分析 Java volatile 变量

1.Java内存模型(Java Memory Model) Java内存模型(JMM),不同于Java运行时数据区,JMM的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中读取数据这样的底层细节.JMM规定了所有的变量都存储在主内存中,但每个线程还有自己的工作内存(CPU内存),线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝.线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量,工作内存是线程之间独立的,线程之间变量值的传递均需要通过

深入分析 Java 中的中文编码问题--转

几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言.由于人类的语言有太多,因而表示这些语言的符号太多,无法用计算机中一个基本的存储单元—— byte 来表示,因而必须要经过拆分或一些翻译工作,才能让计算机能理解.我们可以把计算机能够理解的语言假定为英语,其它语言要能够在计算机中使用必须经过一次翻译,把它翻译成英语.这个翻译的过程就是编码.所以可以想