HTTP/HTTPS、TCP、UDP、Socket

当在浏览器里面输入 www.baidu.com 的时候会发生什么?

  1. 域名解析(DNS)
    DNS(Domain Name System)服务器进行域名解析成为主机IP。域名解析检查顺序为:浏览器自身的DNS缓存 ——> OS自身缓存 ——> 读取host文件 ——> 本地域名服务器 ——> 权限域名服务器 ——> 根域名服务器。如果没有过期,则本次域名解析结束,域名解析成功后进行后续的操作
  2. TCP 的3次握手,建立连接
  3. 建立连接之后,发起 http/https 请求
  4. 服务器响应 http/https 请求, TCP 4次挥手断开连接, 浏览器的到请求的内容
  5. 浏览器解析 HTML 代码并请求 HTML 中的资源

一 什么是HTTP协议

HTTP(Hyper Text Transfer Protocol)即超文本传输协议,现在基本所有的web项目都遵从HTTP协议(所谓协议就是一种认为规范)。目前绝大多数的HTTP协议使用的都是HTTP/1.1版本。

因为HTTP协议是属于TCP/IP协议簇的,所以在了解HTTP协议之前,有必要知道与HTTP相关的TCP/IP的知识

TCP/IP

TCP/IP是一个协议簇,是由许多协议组成的,TCP/IP按照层次从上到下分为四层:应用层传输层网络层网路接口层。实际上最初的OSI/RM模型分为七层,相关详细参照下图。

详细介绍 👉 传送门

应用层
应用层决定了向用户提供服务时的通信活动,TCP/IP协议簇预存了各类通用的应用服务,比如:FTP、DNS 就是其中的两类,HTTP 协议也处在该层。

传输层
传输层对上应用层,提供处于网络连接中的两台计算机之间的数据传输,在传输层上有两个性质不同的协议:TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Datagram Protocol,用户数据报协议)。

网络层
网络层用来处理在网络上流动的数据包,数据包是网络传输的最小单位,该层规定了通过怎样的路径(传输线路)到达对方的计算机,并把数据包传送给对方。和对方计算机之间通过多台计算机或者网络设备进行传输的时候,网络层所起的作用就是在众多的选项内选择一条传输线路。

网络接口层(链路层)
用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动、NIC(Network Interface Card,网路适配卡,即网卡)、光纤等物理可见部分。硬件范畴的均在网络接口层的作用范围。

TCP/IP具体通信

使用TCP/IP协议簇进行网络通信的时候,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则往应用层走。我们使用HTTP举例来说明。首先作为发送端的客户端在应用层(HTTP协议)发出一个想看某个web页面的HTTP请求,接着为了传输方便,在传输层(TCP协议)把应用层处收到的数据(HTTP请求报文)进行分割,并在各个报文上打上标记序号及端口号后转发给网络层(IP协议)。在网络层,增加作为通信目的地的MAC地址后转发给数据链路层,这样,发送网络的通信请求就准备齐全了。接收端的服务器在链路层接收到数据,按序往上层发送,一直到应用层。当传输到应用层,才能算真正接收到由客户端发送过来的HTTP请求。

发送端在层和层之间传输数据的时候,每经过一层的时候必定会被打上一个属于该层的所属的首部信息。反之,接收端在层和层之间传输数据的时候,每经过一层的时候就会把对应的首部去掉。这种把数据信息包装起来的做法称之为封装(encapsulate)

负责传输的IP协议
IP(Internet Protocol)网际协议位于网络层。几乎所有的使用网络的系统都会用到IP协议,TCP/IP协议簇中的IP指的就是网际协议,需要注意的是IP和IP地址不一样,IP是一种协议名称。

IP协议的作用是将各种数据包传输到对方的终端设备,要确保无误的传送到对方那里,需要满足各类条件,其中两个重要的条件就是IP地址和MAC地址(Media Access Control Address)。IP 地址指明了节点被分配到的地址,MAC 地址是指网卡所属的固定地址。IP 地址可以和 MAC 地址进行配对。IP 地址可以更换,但是 MAC 地址基本不会被改。

使用ARP协议凭借MAC地址进行通信。IP间的通信依赖MAC地址。在网络上,通信的双方在同一局域网(LAN)内的情况是很少的,通常是经过多台计算机和网络设备中转才能连接到对方。而在进行中转时,会利用下一站中转设备的MAC地址来搜索下一个中转目标。这时,会采用ARP协议(Address Resolution Protocol)。ARP 是一种用以解析地址的协议,根据通信方的IP地址就可以反查出对应的MAC地址。

没有人能够全面掌握互联网中的传输状况,即在传输过程中每一个节点只需要了解下一个节点的信息,再往下的信息就交给下个节点去处理就行了。在到达通信目标前的中转过程中,那些计算机和路由器等网络设备只能获悉很粗略的传输路线。 这种机制称为路由选择(routing),有点像快递公司的送货过程。想要寄快递的人,只要将自己的货物送到集散中心,就可以知道快递公司是否肯收件发货,该快递公司的集散中心检查货物的送达地址,明确下站该送往哪个区域的集散中心。接着,那个区域的集散中心自会判断是否能送到对方的家中。我们是想通过这个比喻说明,无论哪台计算机、哪台网络设备,它们都无法全面掌握互联网中的细节。

确保可靠性的TCP

TCP位于传输层,提供可靠的字节流服务。所谓的字节流服务(Byte Stream Service)是指,为了方便传输,将大块数据分割成以报文段(segment)为单位的数据包进行管理。而可靠的传输服务是指,能够把数据准确可靠地传给对方。一言以蔽之,TCP协议为了更容易传送大数据才把数据分割,而且TCP协议能够确认数据最终是否送达到对方。

确保数据能到达目标。为了准确无误地将数据送达目标处,TCP协议采用了三次握手(three-way handshaking)策略。用TCP协议把数据包送出去后,TCP不会对传送后的情况置之不理,它一定会向对方确认是否成功送达。握手过程中使用了TCP的标志(flag) ——SYN(synchronize) 和 ACK(acknowledgement)。发送端首先发送一个带 SYN 标志的数据包给对方。接收端收到后,回传一个带有 SYN/ACK 标志的数据包以示传达确认信息。最后,发送端再回传一个带 ACK 标志的数据包,代表握手结束。若在握手过程中某个阶段莫名中断,TCP协议会再次以相同的顺序发送相同的数据包。除了上述三次握手,TCP协议还有其他各种手段来保证通信的可靠性。

TCP三次握手连接和四次挥手断开过程的理解

  • 第一次握手:建立连接的时候,客户端发送SYN(SYN=j)包到服务器,并进入SYN_SENT状态,等待服务器的确认。SYN(Synchronize Sequence Numbers)同步序列编号。
  • 第二次握手:服务器收到SYN包,必须确认客户SYN(ACK=j+1),同时服务器自己也发一个SYN(SYN=k)包,即SYN+ACK包,此时服务器进入SYN_RECV状态
  • 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ACK=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手

  • 客户端进程发出连接释放报文,并且停止发送数据,释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经发送过来的数据最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。TCP规定,FIN报文段即使不携带数据,也要消耗一个序号
  • 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态,TCP通知上层应用进程,客户端向服务器的方向就释放了,这时出于半关闭状态,即客户端已经没有数据要发送了,但是服务器如果要发送数据,客户端依然需要接受。这个状态还要持续一段时间,这个时间就是CLOSE-WAIT的持续时间
  • 客户端收到服务器的确认请求之后,此时客户端进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要就收服务器发送最后的数据)
  • 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假设此时的序列号为seq=w,此时,服务器就进入了LAST-ACk(最后确认)状态,等待客户端的确认。
  • 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态
  • 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

面试可能会遇到的问题😂😂😂

Question:为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为服务器端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文,其中ACK报文是用来应答的,SYN报文是用来同步。但是关闭连接的时候,当服务器收到FIN报文时,有可能不会立即关闭Socket,所以只能先回复一个ACK报文,告诉客户端FIN报文已经收到,只有等服务器端的所有报文都发送完毕,服务器端才会发送FIN报文,因此不能一起发送,所以需要四步握手。

Question:为什么TIME_WAIT状态需要经过2MSL(Maximum Segment Lifetime,最大报文段生存时间)才能返回到CLOSE状态?
正常情况下,四个报文发送完毕,客户端可以直接进入CLOSE状态了,但是我们必须假设网络是不可靠的,可能最后一个ACK会丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在客户端发出最后的ACK之后,但该ACK可能会丢失,服务器如果没有接收到ACK,将不断重复发送FIN片段。所以客户端不能立即关闭,它必须确认服务器接收到了ACK。客户端会在发送ACK之后进入TIME_WAIT状态,客户端会设置一个计时器,等待2MSL的时间,如果在该时间内收到FIN片段,那么客户端会再次重发ACK并再次等待2MSL时间。如果直到2MSL客户端都没有收到FIN,那么客户端认为ACK已经被服务器成功接收,从而结束连接。

Question:为什么不能两次握手?
三次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已经准备好),也要允许双方序列号进行协商,这个序列号seq在握手过程中被发送和确认。现在把三次握手改成仅需要两次握手,可能发生死锁。假设计算机A和B之间通信,当B给A发送一个连接请求分组,A收到分组之后,并发送了确认分组应答。按照两次握手的协定,A认为连接已经成功建立了,可以开始发送数据分组,但是如果B在A的应答分组在传输过程中被丢失,B将不知道A是否已经准备好,在这种情况下,B认为连接还没有建立,将忽略A发过来的任何分组,只等待连接确认应答分组,而在A发送分组超时后,重复发送同样的分组,这样就形成了死锁。

Question:如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

动态演示三次握四次挥手

负责域名解析的DNS服务
DNS(Domain Name System)服务是和HTTP协议一样处在应用层,他提供域名到IP地址之间的解析服务。计算机可以被赋予IP地址,也可以被赋予主机名和域名。应为域名更加直观,所以用户通常使用主机名的或者域名来访问对方的计算机,而不是使用IP地址的方式。

当我们访问一个网页的时候,各种协议在里面起到的作用如下图所示。


参考文章
最详细的http协议、tcp/ip协议
TCP/IP