作者:Jacky心外无事 来源:https://juejin.im/post/5b1265edf265da6e155d45a9
前言
互联网的原始目的,就是为了传输文本(文本对话)。那我们使用浏览器发送请求后页面是如何呈现在我们面前的呢? 接下来由图片介绍下URL到呈现页面的过程。
一、文本对话–从请求到响应
我们在浏览器中输入一个 URL,回车之后便会在浏览器中观察到页面内容。实际上这个过程是:
(1)浏览器向网站所在的服务器发送了一个 Request(请求)
(2)网站服务器接收到这个Request之后进行处理和解析
(3)然后返回对应的一个Response(响应)给浏览器,Response里面就包含了页面的源代码等内容
(4)浏览器再对其进行解析便将网页呈现了出来。
这个文本对话的过程是建立在怎样的规则上面呢?简单说,这个通信的过程是基于TCP/IP通信协议族规范上实现的,完成从客户端到服务器端等一系列信息交换的流程。
二、TCP/IP 协议族介绍
1、TCP/IP协议族是什么呢?
TCP/IP协议族的目的就是通过建立规则使计算机之间可以进行信息交换。
相互通信的双方就必须基于相同的方法,比如由哪一边先发起通信、使用哪种语言进行通信、怎样结束通信等规则都需要事先确定,我们就把这种规则称为协议(protocol)。通常我们说的TCP/IP协议族是互联网相关的各类协议族的总称。
TCP/IP协议族由那么多的协议组成,那功能上如何划分的呢?
这里就说到TCP/IP重要的层次化划分,按层次可以分为4层:应用层、传输层、网络层和链路层。(层次化的好处在于每个层次内部的设计可以自由改动,并通过各层的接口关联起来,而如果只有一个协议统筹就需要对所有涉及到的部分都重新设计。)
2、TCP/IP各功能层的作用
(1) 应用层:决定了向用户提供应用服务时候的通信活动。应用层负责传送各种最终形态的数据,是直接与用户打交道的层,典型协议是HTTP、FTP等。
(2) 传输层:负责传送文本数据。传输层有两个性质不同的协议: TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Data Protocol,用户数据报协议)。
(3) 网络层:负责分配地址和传送二进制数据,主要协议是IP协议;
(4) 链路层:负责建立电路连接,是整个网络的物理基础,典型的协议包括以太网、ADSL等。
3、TCP/IP 通信传输流
在TCP/IP各功能层之间数据是如何流动传输的呢?
(1)首先作为发送端的客户端在应用层(HTTP 协议)发出的 HTTP请求(如:想浏览www.baidu.com),并生成HTTP报文。
(2)为了传输方便,在传输层(TCP 协议)把从应用层处收到的数据(HTTP 请求报文)进行分割,并在 各个报文上打上标记序号及端口号后转发给网络层。
(3)在网络层(IP 协议),增加作为通信目的地的 MAC 地址后转发给链路层。
(4)给这些数据附加上以太网首部并进行发送处理,生成的以太网数据包将通过物理层传输给接收端。
(5)接收端的服务器在链路层接收到数据,按序往上层发送,一直到应用层。当传输到应用层,才能算真正接收到由客户端发送过来的 HTTP 请求。
在通信过程每经过一层时必定会被打上一个该层所属的首部信息。反之,接收端在层与层传输数据时,每经过一层时会把对应的首部消去。
三、基于TCP/IP通信过程
一张图来说明请求到网页呈现的通信过程( 下图基于IP 协议、TCP 协议 、DNS 服务和HTTP 协议的通信过程),并对每一步做说明:
1、浏览器输入URL发送请求
URL(Uniform Resource Locator,统一资源定位符),是使用 Web 浏览器等访问 Web 页面时需要输入的网页地址。
URL由以下元素组成:
(1) 传送协议:http:或者https:等
(2) 层级URL标记符号:为“//”固定不变
(3) 登录信息: 访问资源需要的凭证信息(可省略)
(4) 服务器地址:通常为域名,有时为IP地址(实际通信中需要通过IP地址访问,域名通过DNS服务器解析出IP地址)
(5) 端口号:以数字方式表示,若为HTTP的默认值“:80”可省略
(6) 路径:以“/”字符区别路径中的每一个目录名称
(7) 查询:GET模式的窗体参数,以“?”字符为起点,每个参数以“&”隔开,再以“=”分开参数名称与数据,通常以UTF8的URL编码,避开字符冲突的问题
(8) 片段:以“#”字符为起点,使用片段标识符通常可标记出已获取资源中的子资源
2、DNS对请求中的URL域名解析
DNS(Domain Name System)服务是和 HTTP协议一样位于应用层的协议,它提供域名到 IP 地址之间的解析服务。
计算机既可以被赋予IP地址,也可以被赋予主机名和域名,用户通常使用主机名或域名来访问对方的计算机,而不是直接通过 IP 地址访问。而计算机相对更容易处理一组数字,这时DNS域名解析服务应运而生。DNS 协议提供通过域名查找 IP 地址(或逆向从 IP 地址反查域名的服务)。
3、HTTP协议生成请求报文
HTTP协议:HyperText Transfer Protocol超文本传输协议位于应用层,决定从客户端到服务器端等一系列通信内容及方式,这通过生成报文并发送完成通信。
(1)请求报文的构成
(2)响应报文的构成
4、TCP协议提供可靠的字节流传输服务
TCP协议:Transmission Control Protocol传输控制协议,位于传输层。
(1)字节流服务(Byte Stream Service)是指,为了方便传输,将大块数据分割成以报文段(segment) 为单位的数据包进行管理。
(2)可靠的传输服务是指,能够把数据准确可靠地传给对方。TCP 协议采用了三次握手连接等策略保证传输的可靠性(三次握手,四次挥手文末会有重点补充)
5、IP协议实现数据传递到对方计算机
IP(Internet Protocol)网际协议位于网络层。 IP协议的作用在于实现数据包传递到对方计算机IP地址。而IP间的通信依赖于MAC 地址(网卡所属的固定地址),还需要再通过ARP 协议根据通信方的 IP 地址反查出对应的MAC 地址。
6、接收并解析请求报文后回传响应报文
接收端(服务器)响应报文同样利用TCP/IP通信协议回传
四、TCP建立连接及断开(重点补充)
TCP建立连接(3次握手)
TCP 提供面向有连接的通信传输,面向有连接是指在数据通信开始之前先做好两端之间的准备工作。 三次握手是指建立一个TCP连接时需要客户端和服务器端总共发送三个标记包以确认连接的建立。下面来看看三次握手的流程图:
第一次握手:客户端将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给服务器端,客户端进入SYN_SENT状态,等待服务器端确认。
第二次握手:服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。
第三次握手:客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手建立连接,随后客户端与服务器端之间可以开始传输数据了。
为什么3次握手: 前两次的握手很显然是必须的,主要是最后一次,即客户端收到服务端发来的确认后为什么还要想服务端再发送一次确认呢?这主要是为了防止已失效的请求报文段突然又传送到了服务端而产生连接的误判。
考虑如下的情况: 客户端发送了一个连接请求报文段到服务端,但是在某些网络节点上长时间滞留了,所以客户端又超时重发了一个连接请求报文段该服务端,而后正常建立连接,数据传输完毕,并释放了连接。 如果这时候第一次发送的请求报文段(已过期的)延迟了一段时间后,又到了服务端,很显然,这本是一个早已失效的报文段,但是服务端收到后会误以为客户端又发出了一次连接请求,于是向客户端发出确认报文段,并同意建立连接。假设不采用三次握手,这时服务端只要发送了确认,新的连接就建立了。但由于客户端现阶段没有发出建立连接的请求,因此不会理会服务端的确认,也不会向服务端发送数据,而服务端却认为新的连接已经建立了,并在一直等待客户端发送数据,这样服务端就会一直等待下去,直到超出保活计数器的设定值,而将客户端判定为出了问题,才会关闭这个连接。这样就浪费了很多服务器的资源。而如果采用三次握手,客户端没有再向服务端发出确认,服务端由于收不到确认,就知道客户端没有要求建立连接,从而不建立该连接。
TCP断开连接(4次挥手)
TCP连接是全双工的,因此,每个方向都必须要单独进行关闭, 四次挥手即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。 下面来看看四次挥手的流程图:
注:中断连接端可以是客户端,也可以是服务器端。下文举的例子是以客户端发出中断请求。
第一次挥手:客户端发送一个FIN=M,用来关闭客户端到服务器端的数据传送,客户端进入FIN_WAIT_1状态。意思是说"我客户端没有数据要发给你了",但是如果你服务器端还有数据没有发送完成,则不必急着关闭连接,可以继续发送数据。
第二次挥手:服务器端收到FIN后,先发送ack=M+1,告诉客户端,“你的请求我收到了,但是我还没准备好,请继续你等我的消息。”这个时候客户端就进入FIN_WAIT_2状态,继续等待服务器端的FIN报文。
第三次挥手:当服务器端确定数据已发送完成,则向客户端发送FIN=N报文,告诉客户端,好了,我这边数据发完了,准备好关闭连接了。服务器端进入LAST_ACK状态。
第四次挥手:客户端收到FIN=N报文后,就知道可以关闭连接了,但是他还是不相信网络,怕服务器端不知道要关闭,所以发送ACK=1,ack=N+1后进入TIME_WAIT状态,如果服务器端没有收到ACK则可以重传。服务器端收到ACK后,就知道可以断开连接了(CLOSED状态)。客户端等待了2MSL(时间MSL叫做最长报文寿命,RFC建议设为2分钟)后依然没有收到回复,则证明服务器端已正常关闭,客户端也可以关闭连接了。最终完成了四次握手。
为什么4次挥手:TCP协议是一种面向连接的、可靠的字节流的运输层通信协议,TCP是全双工模式,这就意味着,当客户端发出FIN报文段时,只是表示客户端已经没有数据要发送了,客户端告诉服务器,它的数据已经全部发送完毕了;但是,这个时候客户端还是可以接受来自服务器的数据;当服务器返回ACK报文段时,表示它已经知道客户端没有数据发送了,但是主机2还是可以发送数据到客户端的;当服务器也发送了FIN报文段时,这个时候就表示服务器也没有数据要发送了,就会告诉客户端,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。
为什么客户端TIME_WAIT等待2MSL: (1)为了保证客户端发送的最后一个ACK报文段能够到达服务器。该ACK报文段很有可能丢失,因而使处于在LIST—ACK状态的服务器收不到对已发送的FIN+ACK报文段的确认,服务器可能会重传这个FIN+ACK报文段,而客户端就在这2MSL时间内收到这个重传的FIN+ACK报文段,接着客户端重传一次确认,重新启动2MSL计时器,最后客户端和服务器都进入CLOSED状态。(2)防止已失效的请求连接出现在本连接中。在连接处于2MSL等待时,任何迟到的报文段将被丢弃,因为处于2MSL等待的,由该插口(插口是IP和端口对的意思,socket)定义的连接在这段时间内将不能被再用,这样就可以使下一个新的连接中不会出现这种旧的连接之前延迟的报文段。
小结
以上,我们了解TCP/IP协议的作用及通信的流程,针对Http协议后续再做详细介绍。