1. 互联网和传输层协议
互联网是一个非常庞大的结构,从整体来看,互联网是一个立体的、庞大的网状结构。但是如果将它放大、再放大,将镜头拉近,在微观层面,我们会看到一个个网络、一台台设备,还会看到大量的封包在交换、有设备在不断地改变封包的走向、损坏的封包被重发、一个个光电信号被转化和传输。
名词:
- 本地网络服务提供商 (Internet Service Provider):移动、联通、电信等。
- 通信链路(Communication Link):两台设备之间的通信链路,同轴电缆是通信链路,无线信号的发送接收器可以构成通信链路,蓝牙信道也可以构成通信链路。
- 交换(Switch):c交换技术的本质,就是让数据切换路径。
- 封包交换技术(Packet Switch):网络中的数据是以分组或封包(Packet)的形式传输,因此交换也称作封包交换。
- 路由器(Router)和链路层交换机(Link-Layer Switch):常见的具有交换能力的设备,两个网络可以通过路由器进行连接,多台设备可以通过交换机进行连接。但是路由器通常也具有交换机的功能。
- 蜂窝塔(Cellular Tower),也称作基站(BaseStation):移动网络的中,通信的核心
1.1 传输层协议TCP
1.1.1 概念
- TCP 协议:TCP(Transport Control Protocol)是一个传输层协议,提供 Host-To-Host 数据的可靠传输,支持全双工,是一个连接导向的协议。
- 主机到主机(Host-To-Host):主机到主机(Host-To-Host)为应用提供应用间通信的能力。
- TCP/IP 5层模型:应用层—》传输层—》网络层—》数据链路层—》物理层
- 什么是连接和会话?:连接(Connection)——连接是数据传输双方的契约。连接是网络行为状态的记录。会话(Session),会话是应用的行为。会话是应用层的概念,连接是传输层的概念。
双工/单工问题:TCP 是一个双工协议,数据任何时候都可以双向传输。
- 单工:单工需要至少一条线路,数据只能单向发送。
- 半双工:半双工需要至少 1 条线路,同一时间只能单向发送数据。
- 全双工:全双工需要大于 1 条线路,任何时刻数据都可以双向收发。
- 什么是可靠性:可靠性指数据保证无损传输。
- 多播:如果发送方同时要把消息发送给多个接收方,这种情况叫作多播,可靠性要求每个接收方都无损收到相同的副本。多播情况还有强可靠性,就是如果有一个消息到达任何一个接收者,那么所有接受者都必须收到这个消息。我们接下来说的可靠性值得都是单播的可靠性。
- TCP的握手和挥手:TCP 是一个连接导向的协议,设计有建立连接(握手)和断开连接(挥手)的过程。
TCP协议的基本操作:
- 如果一个 Host 主动向另一个 Host 发起连接,称为 SYN(Synchronization),请求同步;
- 如果一个 Host 主动断开请求,称为 FIN(Finish),请求完成;
- 如果一个 Host 给另一个 Host 发送数据,称为 PSH(Push),数据推送。
- 以上 3 种情况,接收方收到数据后,都需要给发送方一个 ACK(Acknowledgement)响应
建立连接的过程(三次握手):
- 客户端发消息给服务端(SYN)。(第一次握手)
- 服务端准备好进行连接。
- 服务端针对客户端的 SYN 给一个 ACK,同时服务端发送一个 SYN 给客户端。(第二次握手)
- 客户端准备就绪。
- 客户端给服务端发送一个 ACK。(第三次握手)
断开连接的过程(4次挥手)
- 客户端发送断开请求(FIN)。
- 服务端收到请求,返回ACK,作为FIN的响应。
- 服务端经过等待,确定可以关闭连接了发送FIN给客户端。
有资源需要释放,有消息没有得到ACK等,需要等待待处理问题处理完毕,确定服务器端可以断开连接
- 客户端收到FIN,客户端自己处理完成之后发送一个ACK。
例如有消息没有收到ACK,但因为是主动放没有过多任务需要处理。
1.1.2 总结
- TCP 提供连接(Connection),让双方的传输更加稳定、安全。
- TCP 没有直接提供会话,因为应用对会话的需求多种多样,比如聊天程序会话在保持双方的聊天记录,电商程序会话在保持购物车、订单一致,所以会话通常在 TCP 连接上进一步封装,在应用层提供。
- TCP 是一个面向连接的协议(Connection -oriented Protocol),说的就是 TCP 协议参与的双方(Host)在收发数据之前会先建立连接。后面我们还会学习 UDP 协议,UDP 是一个面向报文(Datagram-oriented)的协议——协议双方不需要建立连接,直接传送报文(数据)。
- 最后,连接需要消耗更多的资源。比如说,在传输数据前,必须先协商建立连接。因此,不是每种场景都应该用连接导向的协议。像视频播放的场景,如果使用连接导向的协议,服务端每向客户端推送一帧视频,客户端都要给服务端一次响应,这是不合理的。
1.1.3 TCP 为什么握手是 3 次、挥手是 4 次?
TCP 是一个双工协议,为了让双方都保证,建立连接的时候,连接双方都需要向对方发送 SYC(同步请求)和 ACK(响应)。
握手阶段双方都没有烦琐的工作,因此一方向另一方发起同步(SYN)之后,另一方可以将自己的 ACK 和 SYN 打包作为一条消息回复,因此是 3 次握手——需要 3 次数据传输。
到了挥手阶段,双方都可能有未完成的工作。收到挥手请求的一方,必须马上响应(ACK),表示接收到了挥手请求。类比现实世界中,你收到一个 Offer,出于礼貌你先回复考虑一下,然后思考一段时间再回复 HR 最后的结果。最后等所有工作结束,再发送请求中断连接(FIN),因此是 4 次挥手。
1.2 为什么要粘包和拆包?
1.2.1 理解TCP 的拆包和粘包
TCP 是一个传输层协议。TCP 发送数据的时候,往往不会将数据一次性发送,而是将数据拆分成很多个部分,然后再逐个发送。
TCP 为什么不一次发送完所有的数据?
- 为了稳定性,一次发送的数据越多,出错的概率越大。
- 为了效率,网络中有时候存在着并行的路径,拆分数据包就能更好地利用这些并行的路径。
- 比如发送和接收数据的时候,都存在着缓冲区。缓冲区是在内存中开辟的一块区域,目的是缓冲。因为大量的应用频繁地通过网卡收发数据,这个时候,网卡只能一个一个处理应用的请求。当网卡忙不过来的时候,数据就需要排队,也就是将数据放入缓冲区。如果每个应用都随意发送很大的数据,可能导致其他应用实时性遭到破坏。
- 内存的最小分配单位是页表,如果数据的大小超过一个页表,可能会存在页面置换问题,造成性能的损失。
- 总之,方方面面的原因:在传输层封包不能太大。
- 拆包:数据经过拆分,然后传输,然后在目的地重组,俗称拆包。所以拆包是将数据拆分成多个 TCP 段传输。
- 粘包:如果发往一个目的地的多个数据太小了,为了防止多次发送占用资源,TCP 协议有可能将它们合并成一个 TCP 段发送,在目的地再还原成多个数据,这个过程俗称粘包。所以粘包是将多个数据合并成一个 TCP 段发送。
- TCP Segment:TCP段
- Source Port/Destination Port 描述的是发送端口号和目标端口号,代表发送数据的应用程序和接收数据的应用程序。
- Sequence Number 和 Achnowledgment Number 是保证可靠性的两个关键。
- Data Offset 是一个偏移量。这个量存在的原因是 TCP Header 部分的长度是可变的,因此需要一个数值来描述数据从哪个字节开始。
- Reserved 是很多协议设计会保留的一个区域,用于日后扩展能力。
URG/ACK/PSH/RST/SYN/FIN 是几个标志位,用于描述 TCP 段的行为。也就是一个 TCP 封包到底是做什么用的?
- URG 代表这是一个紧急数据,比如远程操作的时候,用户按下了 Ctrl+C,要求终止程序,这种请求需要紧急处理。
- ACK 代表响应,所有的消息都必须有 ACK,这是 TCP 协议确保稳定性的一环。
- PSH 代表数据推送,也就是在传输数据的意思。
- SYN 同步请求,也就是申请握手。
- FIN 终止请求,也就是挥手。
- Window 也是 TCP 保证稳定性并进行流量控制的工具
- Checksum 是校验和,用于校验 TCP 段有没有损坏。
- Urgent Pointer 指向最后一个紧急数据的序号(Sequence Number)。它存在的原因是:有时候紧急数据是连续的很多个段,所以需要提前告诉接收方进行准备。
- Options 中存储了一些可选字段,比如接下来我们要讨论的 MSS(Maximun Segment Size)。
- Padding 存在的意义是因为 Options 的长度不固定,需要 Pading 进行对齐。
Sequence Number 和 Acknowledgement Number:
- 发送放已经发送了多少数据。用Sequence Number表示。
- 发送方已经接收了多少数据。用 Acknowledgement Number 表示。
- MSS(Maximun Segment Size):最大报文段长度。
这是一个协商字段,涉及发送、接收缓冲区的大小设置,双方实际发送接收封包的大小,对拆包和粘包的过程有指导作用,因此需要双方去协商。
如果设置得非常大,首先对方可能会拒绝,因为大的 TCP 段,会降低性能,比如内存使用的性能。还有就是资源的占用。一个用户占用服务器太多的资源,意味着其他的用户就需要等待或者降低他们的服务质量。IP 协议,工作效率会下降,TCP 协议不肯拆包,IP 协议就需要拆出大量的包。因为在网络中,每次能够传输的数据不可能太大,这受限于具体的网络传输设备,也就是物理特性。
MSS 太小的情况下,会浪费传输资源(降低吞吐量)。因为数据被拆分之后,每一份数据都要增加一个头部。如果 MSS 太小,那头部的数据占比会上升,这让吞吐量成为一个灾难。
所以在使用的过程当中,MSS 的配置,往往都是一个折中的方案。
1.2.2 TCP 协议是如何恢复数据的顺序的?拆包和粘包的作用是什么?
TCP 拆包的作用是将任务拆分处理,降低整体任务出错的概率,以及减小底层网络处理的压力。拆包过程需要保证数据经过网络的传输,又能恢复到原始的顺序。这中间,需要数学提供保证顺序的理论依据。TCP 利用(发送字节数、接收字节数)的唯一性来确定封包之间的顺序关系。
1.3 滑动窗口和流速控制是怎么回事?
TCP 作为一个传输层协议,最核心的能力是传输。传输需要保证可靠性,还需要控制流速,这两个核心能力均由滑动窗口提供。
1.3.1 请求/响应模型
TCP 中每个发送的请求都需要响应。如果一个请求没有收到响应,发送方就会认为这次发送出现了故障,会触发重发。
线性结构的请求相应模型吞吐量低,不适用
有请求就发送出去,而不是等待响应。提高吞吐量但当TCP段非常多时,带宽不足
1.3.2 滑动窗口(Sliding Window)
我们将已发送的数据放到最左边,发送中的数据放到中间,未发送的数据放到右边。如果一个ACK到达,我们将他标记为已发送,当左侧出现已发送时,窗口向右滑动。
1.3.3 重传
如果发送过程中,部分数据没能收到ACK,就可能发生重传。
如果4号迟迟没有收到ACK,这时滑动窗口只能向右滑动一个位置,在接下来如果段4重传成功,则窗口继续右移,如果段4发送失败,还是没能收到ACK,那么接收方也会抛弃5,6,7。这样段4开始之后的数据都需要重发。
1.3.4 快速重传
如果接收方想丢弃某个段,可以选择不发ACK,发送端超时后,会重发TCP端。
如果接收方希望督促发送方尽快补发某个TCP段,收方可以发送多次段 3 的 ACK。如果发送方收到多个段 3 的 ACK,就会重发段 3。这个机制称为快速重传。
为了不让发送方误以为段 3 已经收到了,在快速重传的情况下,接收方即便收到发来的段 4,依然会发段 3 的 ACK(不发段 4 的 ACK),直到发送方把段 3 重传。
思考:窗口大小的单位是?
实际操作中,每个 TCP 段的大小不同,限制数量会让接收方的缓冲区不好操作,因此实际操作中窗口大小单位是字节数。
1.3.5 流速控制
发送、接收窗口的大小可以用来控制 TCP 协议的流速。窗口越大,同时可以发送、接收的数据就越多,支持的吞吐量也就越大。当然,窗口越大,如果数据发生错误,损失也就越大,因为需要重传越多的数据。
举个例子:我们用 RTT 表示 Round Trip Time,就是消息一去一回的时间。
假设 RTT = 1ms,带宽是 1mb/s。如果窗口大小为 1kb,那么 1ms 可以发送一个 1kb 的数据(含 TCP 头),1s 就可以发送 1mb 的数据,刚好可以将带宽用满。如果 RTT 再慢一些,比如 RTT = 10ms,那么这样的设计就只能用完 1/10 的带宽。 当然你可以提高窗口大小提高吞吐量,但是实际的模型会比这个复杂,因为还存在重传、快速重传、丢包等因素。
1.3.6 滑动窗口和流速控制是怎么回事?
滑动窗口是 TCP 协议控制可靠性的核心。发送方将数据拆包,变成多个分组。然后将数据放入一个拥有滑动窗口的数组,依次发出,仍然遵循先入先出(FIFO)的顺序,但是窗口中的分组会一次性发送。窗口中序号最小的分组如果收到 ACK,窗口就会发生滑动;如果最小序号的分组长时间没有收到 ACK,就会触发整个窗口的数据重新发送。
另一方面,在多次传输中,网络的平均延迟往往是相对固定的,这样 TCP 协议可以通过双方协商窗口大小控制流速。
1.4 TCP 协议和 UDP 协议的优势和劣势?
TCP 最核心的价值是提供了可靠性,而 UDP 最核心的价值是灵活,你几乎可以用它来做任何事情。
1.4.1 概念
- UDP协议:UDP(User Datagram Protocol),目标是在传输层提供直接发送报文(Datagram)的能力。Datagram 是数据传输的最小单位。UDP 协议不会帮助拆分数据,它的目标只有一个,就是发送报文。
- UDP 的封包格式:
- Source Port 是源端口号。因为 UDP 协议的特性(不需要 ACK),因此这个字段是可以省略的。但有时候对于防火墙、代理来说,Source Port 有很重要的意义,它们需要用这个字段行过滤和路由。
- Destination Port 是目标端口号(这个字段不可以省略)
- Length 是消息体长度。
- Checksum 是校验和,作用是检查封包是否出错。
checksum=(a+b+c+d) ^ 0xff
如果发送方用上述方式计算出 Checksum,并将 a,b,c,d 和 Checksum 一起发送给接收方,接收方就可以用同样的算法再计算一遍,这样就可以确定数据有没有发生损坏(变化)
- Data octets 就是一个字节一个字节的数据,Octet 是 8 位。
UDP 与 TCP的区别:
- 目的差异:TCP 协议的核心目标是提供可靠的网络传输,而 UDP 的目标是在提供报文交换能力基础上尽可能地简化协议轻装上阵。
- 可靠性差异:
- 连接 vs 无连接:TCP 是一个面向连接的协议(Connection-oriented Protocol),传输数据必须先建立连接。 UDP 是一个无连接协议(Connection-less Protocol),数据随时都可以发送,只提供发送封包(Datagram)的能力。
- 流控技术(Flow Control):TCP 使用了流控技术来确保发送方不会因为一次发送过多的数据包而使接收方不堪重负。TCP 在发送缓冲区中存储数据,并在接收缓冲区中接收数据。当应用程序准备就绪时,它将从接收缓冲区读取数据。如果接收缓冲区已满,接收方将无法处理更多数据,并将其丢弃。UDP 没有提供类似的能力。
- 传输速度:UDP 协议简化,封包小,没有连接、可靠性检查等,因此单纯从传输速度上讲,UDP 更快。
1.4.2 TCP 协议和 UDP 协议的优势和劣势?
TCP 最核心的价值就是提供封装好的一套解决可靠性的优秀方案。UDP 则不同,UDP 提供了最小版的实现,只支持 Checksum。UDP 最核心的价值是灵活、轻量、传输速度快。