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不同的是数据的写入和读取还要有一个协调的过程,如果在两边同时传送数据可能会产生死锁。

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

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

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

    I/O 问题可以说是当今互联网 Web 应用中所面临的主要问题之一,因为当前在这个海量数据时代,数据在网络中随处流动.这个流动的过程中都涉及到 I/O 问题,可以说大部分 Web 应用系统的瓶颈都是 ...

  2. JAVA Coder 的《深入分析Java Web 技术内幕》读书笔记

    本文基于<深入分析Java Web 技术内幕> <深入分析Java Web 技术内幕>,作者是 许令波,电子工业出版社.本文只是记录书本当中的精彩部分,作个人回顾和技术分享,请 ...

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

    Java 的 I/O 类库的基本架构 I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道.在当今这个数据大爆炸时代, ...

  4. 第二章 深入分析Java I/O的工作机制(待续)

    Java的I/O类库的基本架构 磁盘I/O工作机制 网络I/O工作机制 NIO的工作方式 I/O调优 设计模式解析之适配器模式 设计模式解析之装饰器模式 适配器模式与装饰器模式的区别

  5. Servlet工作原理解析 《深入分析java web 技术内幕》第九章

    参考关于servblet的相关文章 侧重概况:https://blog.csdn.net/levycc/article/details/50728921 ibm的相关:https://www.ibm. ...

  6. 深入理解Java虚拟机学习笔记(三)-----类文件结构/虚拟机类加载机制

    第6章 类文件结构 1. 无关性 各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节码(即扩展名为 .class 的文件) 是构成平台无关性的基石. 字节码(即扩展名为 .class 的文 ...

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

    JVM(三):深入分析Java字节码-上 字节码文章分为上下两篇,上篇也就是本文主要讲述class文件存在的意义,以及其带来的益处.并分析其内在构成之一 ---字节码,而下篇则从指令集方面着手,讲解指 ...

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

    概述 Java IO即Java 输入输出系统.不管我们编写何种应用,都难免和各种输入输出相关的媒介打交道,其实和媒介进行IO的过程是十分复杂的,这要考虑的因素特别多,比如我们要考虑和哪种媒介进行IO( ...

  9. 深入分析Java Web技术内幕(修订版)

    阿里巴巴集团技术丛书 深入分析Java Web技术内幕(修订版)(阿里巴巴集团技术丛书.技术大牛范禹.玉伯.毕玄联合力荐!大型互联网公司开发应用实践!) 许令波 著   ISBN 978-7-121- ...

随机推荐

  1. dt常用类

    经常使用的一些datatable的操作,包括一些过滤去重的方法 using System; using System.Collections; using System.Collections.Gen ...

  2. lumen框架学习01——引入自定义类和函数

    引入自定义的functions.php文件,首先把functions.php文件放在app的目录下,然后通过根目录的composer.json文件引入,具体操作如下图: 引入类文件也是一样,具体可参考 ...

  3. mysql中的concat函数,concat_ws函数,concat_group函数之间的区别

    一.CONCAT()函数CONCAT()函数用于将多个字符串连接成一个字符串.使用数据表Info作为示例,其中SELECT id,name FROM info LIMIT 1;的返回结果为+----+ ...

  4. Java+Selenium自动化对非输入框的日历或日期控件的处理

    如图:          1.问题描述: 在应用selenium实现web自动化时,经常会遇到处理日期控件点击问题,手工很简单,可以一个个点击日期控件选择需要的日期,但自动化执行过程中,完全复制手工这 ...

  5. linux系统下部署DNS反向解析

    DNS服务概述 DNS(Domain Name System)域名系统,能够提供域名与IP地址的解析服务. 反向解析 反向解析是从IP地址到域名的解析过程.主要作用于服务器的身份验证. 部署反向解析 ...

  6. NodeJS (npm) 学习笔记

    零, npm是nodeJS的包管理器,下载nodeJS后会自动安装好npm. 一,windows下安装 nodeJS并配置(以及angular安装相关问题) 1, 下载安装 https://nodej ...

  7. mpvue 初体验之改写车标速查小程序

    前文 说到我开发了一个简单的小程序叫做 车标速查(代码以及二维码详见 这里),本文简单讲讲如何将这个小程序转为 mpvue 开发(最终 成果 ) mpvue 官网的 文档 真的是非常简单,不,应该说是 ...

  8. Django 执行单独脚本及SyntaxError缩进报错解决

    有时候会碰到这样的场景,对于一些业务升级,我需要把数据库数据做些处理,同时又想以 Django 项目的环境变量执行脚本,这个时候使用 python 脚本是再适合不过的手段了. 注意:在pycharm里 ...

  9. quartus 一种管脚分配方法

    第一步: 在QII软件中,使用“Assignments -> Remove Assignments”标签,移除管脚分配内容,以确保此次操作,分配的管脚没有因为覆盖而出现错误的情况. 编写xxx. ...

  10. Navicat连接oracle库报错的处理方法

    1.oracle客户端版本:11.2.0  64X navicat premium客户端:12.0. 64X 2.安装后,打开连接,输入连接信息,点击保存,提示oracle library is no ...