1.1 OSI 七层参考模型
七层模型,亦称 OSI(Open System Interconnection)参考模型,即开放式系统互联,是网络通信的标准模型。一般称为 OSI 参考模型或七层模型。
它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。
- 物理层:负责传输原始的比特流,数模转换、模数转换。
- 数据链路层:负责在直接相连的节点之间可靠地传输数据帧,进行错误检测和纠正,以及定义物理地址(MAC地址)。
- 网络层:负责在网络中的不同节点之间进行数据包的传输和路由选择,使用逻辑地址(IP地址)进行寻址。
- 传输层:负责提供端到端的数据传输服务,确保数据可靠地传输,处理数据分段和重组,提供差错恢复和流量控制等功能。
- 会话层:负责建立、管理和终止应用程序之间的会话(Session),提供数据同步和会话恢复等功能。
- 表示层:负责数据的格式化和解析,进行数据的加密和解密,以及处理数据的压缩和转换等操作。
- 应用层:负责提供网络应用程序之间的通信服务,包括文件传输、电子邮件、远程登录等各种应用。
1.2 TCP/IP模型
TCP/IP模型是工程中实际使用的模型,在工程实现中只需要关注传输层、应用层即可!
面试问题:OSI 模型与 TCP/IP 模型的区别是什么?
OSI(Open Systems Interconnection,开放系统互联),是⽹络通信的标准模型,但是TCP/IP模型是事实模型,对OSI模型进⾏了简化。
TCP/IP模型与之的区别在于:下2层物理层和数据链路层合并为数据链路层;上3层会话层、表示层、应⽤层合并为应⽤层;
套接字(Socket)作为传输层以下⽹络的封装,为上⾯三层提供了统⼀的接口。之所以这么做,有如下好处:
1)上三层⽤于处理应⽤的业务细节,⽽不关注通信细节,差异性较⼤;下四层实现通信细节,⽽不关注业务细节,更加通⽤;
2)上三层通常处于⽤户进程内,⽽下四层作为OS内核的⼀部分提供;
1.3 TCP/IP协议族
- TCP:Transmission Control Protocol,传输控制协议。⼀个⾯向连接的协议,提供可靠全双⼯字节流(全双工(Full Duplex)是一种通信方式,允许数据同时在两个方向上进行双向传输,即发送端和接收端可以同时发送和接收数据。),使⽤流套接字(流套接字适用于需要可靠数据传输和双向通信的场景,如文件传输、HTTP通信等)。具有消息确认、超时、重传等机制;
- UDP:User Datagram Protocol,⽤户数据报协议。⼀个⽆连接协议,使⽤数据报套接字(数据报套接字适用于对实时性要求较高、对数据传输顺序和可靠性要求较低的场景,如音视频传输、DNS查询等),不能保证消息递送⼀定成功;
- SCTP:Stream Control Transmission Protocol,流控制传输协议。提供可靠全双⼯⾯向连接的协议。SCTP是多宿的,通信的两端可以涉及多组(IP,端⼝)通信。提供消息服务;(SCTP和TCP的主要区别是SCTP提供了多流和多宿的能力)
- IPv4:Internet Protocol version 4,使⽤32位地址(可用地址有限);
- ICMP:Internet Control Message Protocol,⽹络控制消息协议,处理主机和路由之间的消息通信;
- IGMP:Internet Group Management Protocol,⽹络组管理协议,⽤于⼴播通信;
- ARP:Address Resolution Protocol,地址解析协议,把IPv4地址映射成⼀个硬件地址(MAC地址),⽤于⼴播⽹络;
- RARP:Reverse Address Resolution Protocol,反向地址解析协议,把硬件地址(MAC地址)映射成IPv4地址;
- IPv6:Internet Protocol version 6,使⽤64位地址(可用地址空间巨大);
- ICMPv6:Internet Control Message Protocol version 6,为IPv6协议提供地址解析、⽹络组管理等功能,兼具ICMPv4、IGMP、ARP协议的功能;
- BPF:BSD packet filter,BSD分组过滤器。提供数据链路层的访问能⼒;(Berkeley内核);
- DLPI:datalink provider interface,数据链路提供者接⼝。提供数据链路层的访问能⼒;(SVR4内核);
1.4 TCP/UDP/SCTP协议
(1)UDP协议:无连接的传输协议,封装应用层数据到一个UDP数据报中,之后再将UDP数据报封装到IP数据报中,发送出去;
1)UDP数据报具有长度(消息长度是用来告诉客户端在读取数据报时的起始和结束),消息长度随着报文传递到对端(而非TCP的流式消息);
2)UDP协议不具备传输的可靠性:不提供确认、序列号、R1TT估算、超时、重传等机制;
数据报(Datagram)和数据流(Stream)是在网络通信中常用的两种数据传输方式,它们有以下区别:
- 数据报是一种面向无连接的传输方式,每个数据报都是独立的、自包含的数据单元。
- 每个数据报都有自己的目标地址和源地址,可以独立地通过网络进行传输。
- 数据报的传输是不可靠的,可能会发生丢包、重复、乱序等问题。
- 数据流是一种面向连接的传输方式,数据在发送端和接收端之间建立一个持久的、有序的字节流。
- 数据流的传输是可靠的,确保数据的有序、完整和无错误地传输。
数据报和数据流是两种不同的数据传输方式。数据报是独立的、自包含的数据单元,每个数据报都有自己的目标地址和源地址,传输是不可靠的。数据流是建立在连接上的持久字节流,传输是可靠的,确保数据的有序、完整和无错误传输。选择使用哪种方式取决于具体的应用需求和通信方式的特点。
(2)TCP协议:有连接协议,基于数据流,会将上层消息封装为多个个分节,每个分节以一个IP数据报发送;
2)TCP协议保证传输的可靠性(更加可靠,而非100%可靠);
- 提供对端消息确认机制:消息发出后等待对端确认,才视作成功;
- 提供超时和重传机制:消息发送后,超过一定时间未收到确认,则重发消息;直至成功或者超过指定重试时间;
- 提供RTT估算:提供动态估算客户端与服务器之间的RTT(round-triptime)算法,以便知道一次RTT大概耗时;
- 提供消息序列号:对个分节提供一个序列号(字节偏移量),以便对端在收到消息时,根据序列号进行消息的排序和去重;
- 提供流量控制:提供通告窗口(advertised window)告知对端,当前能够接收多少数据;从而确保发送端发送的数据量不会使接收缓冲区溢出;通告窗口随着消息的接收动态变化,当为0时,表示接收缓冲区已满,需要等待应用从缓冲区读取数据后,才能再次从对端接收数据;即TCP负反馈机制,通过接收端的速率限制发送端的速率;
注:TCP协议并不能保证100%的可靠性,而是在尽可能保证可靠性的前提下,能够让上层感知消息传递的异常;
4)TCP协议是全双工(full-duplex)协议,给定连接上应用可以在任何时刻即发送数据又接收数据;
(3)SCTP协议:有连接协议,提供可靠性、排序、流控、全双工的为数据传送;通过关联(association)表示两端的通信方式,一个连接只涉及两个IP地址间的通信;而一个关联指代两端的第一次通信,但不一定是两个IP地址间的通信;
1)SCTP是面向消息的,有消息长度,各个消息按顺序送达对端(TCP不具有消息长度,依靠上层应用自行设计应用层协议的长度);
2)每个关联包含多个流(连接),单个流上消息丢失,不会阻塞其它流上消息的传输(TCP只具有单个流,会阻塞);
3)SCTP提供多宿特性,即两端能够支持多个IP地址,一个端点可以有多个冗余连接,走不同的基础设施,从而增强应对网络故障的健壮性;
在SCTP(流控制传输协议)中,多流(Multi-Stream)和多宿(Multi-Homing)是其特性之一,提供了更灵活和高效的数据传输能力。
- 多流是指在单个SCTP连接中可以同时传输多个独立的数据流。
- SCTP允许应用程序在同一个SCTP连接上创建多个逻辑流,每个流都有自己的序列号和传输控制。
- 多流特性使得应用程序可以将不同类型的数据分组到不同的流中,实现并行传输和优化网络资源利用。
- 应用程序可以根据需要创建、选择和管理多个流,以满足不同数据流的需求。
- 多宿是指在SCTP连接中可以同时使用多个网络接口或IP地址进行通信。
- SCTP允许一个端点(主机)在多个网络接口上绑定多个IP地址,并在通信过程中根据网络状况选择合适的地址进行数据传输。
- 多宿特性提供了冗余和负载均衡的能力,当一个网络接口或IP地址不可用时,可以自动切换到其他可用的接口或地址。
- 应用程序可以利用多宿特性提高连接的可靠性和可用性,适应多网络环境下的数据传输需求。
1.5 TCP协议
1.5.1 TCP建链:三次握手
1)被动打开(passive open):服务端调⽤socket、bind、listen 3 个函数,启动监听;
2)主动打开(active open):客户端调⽤connect函数连接服务端:客户端发送SYN分节,告知客户端发送初始序列号;SYN分节不携带数据,故其所在的IP数据报只包含⼀个IP头、⼀个TCP头和可选的TCP选项;
3)服务端发送ACK,确认客户端发来的SYN,同时发送⾃⼰的SYN给客户端,告知服务端发送初始序列号;
注2:服务端的初始序列化序列号和客户端的初始化序列号是2个独⽴字段,分别代表各⾃发送的消息序列号;
注3:每次发送SYN,都会携带当前的序列号;每次回复ACK,都会携带下⼀次消息的序列号,即当前序列号+1;
Server:我可以听到,你可以听到吗?(ACK + SYN)
TCP_MAXSEG:设置MSS(Max Segment Size),发送SYN时,告知对端可以接受的最⼤分节⼤⼩;即在当前连接中每个TCP分节中可以接受的最⼤数据量,接收SYN的⼀端会据此设置发送分节的 最⼤⼤⼩。通过TCP_MAXSEG设置;
SO_RCVBUF:设置接收缓冲区⼤⼩,据此告知对端通告窗⼝的⼤⼩;
1.5.2 TCP关闭连接:四次挥⼿
1)主动关闭(active close):A端调⽤close函数,发送⼀个FIN分节,带序列号,告知B端数据发送完毕;
2)被动关闭(passive close):B端收到FIN后,回复ACK分节给A端;同时将接收数据作为⼀个
EOF(⽂件结束符)传递给上层应⽤,通知上层应⽤数据发送完毕;
3)B端上层应⽤收到EOF后,调⽤close函数,同样发送⼀个FIN分节,告知A端数据发送完毕;
4)A端收到FIN分节后,回复⼀个ACK分节给B端;⾄此两端都已关闭;
注1:之所以要两端都发送FIN,是因为TCP是全双⼯,两端都可能发送数据,因此需要两端都发送FIN,告知对端发送完毕;
注2:每次发送FIN,都会携带当前的序列号;每次回复ACK,都会携带下⼀次消息的序列号,即当前序列号+1;
注3:执⾏完1),2)两步后,被动关闭的⼀端(B端)仍然可以向主动关闭的⼀端(A端)发送数据,此时称为半关闭(half-close);
注4:当⼀个Unix进程⽆论⾃愿的终⽌(调⽤exit或者从main返回)还是⾮⾃愿的终⽌(收到⼀个进程终⽌信号),所有打开的⽂件句柄都会被关闭,这也会导致任何打开的TCP连接上也发送⼀个FIN分 节,告知对端关闭;(内核⾏为,这也是进程挂掉,⽽操作系统未宕机时,对端能够⻢上感知到断链 的原因)
注5:⽆论客户端还是服务端,都可以主动关闭连接(调⽤close函数);
问:为什么三次握⼿时,服务端可以在⼀个分节同时回复ACK,SYN。⽽在四次挥⼿中,被动关闭的
因为TCP是全双⼯的,四次挥⼿时,两端的关闭是独⽴动作,可以各⾃控制是否关闭⾃⼰发送消息的 通道。因⽽分为2组消息(⼀条FIN和⼀条ACK);
1)三次握手在第二步中,服务端可以将ACK和SYN的响应合并在一个分节中发送。这是因为服务端在收到客户端的SYN分节后,已经知道了客户端的初始序列号(ISN),并且服务端也需要发送自己的初始序列号(ISN)给客户端。因此,服务端可以将ACK和SYN的响应合并在一个分节中发送,以减少通信的往返时间(RTT)。
2)因为主动断开连接方在断开连接后能收数据但不能发送数据,此时被动断开连接方还没有断开连接,既能接收数据又能发送数据。被动断开连接方和主动断开连接方可能还有别的需求,因此需要单独执行ACK和SYN
1.6 TCP状态机
服务端建链状态机
CLOSED -> LISTEN:服务端调⽤listen函数,被动打开;
LISTEN -> SYN_RCVD:服务端接收SYN,发送SYN + ACK;
SYN_RCVD -> ESTABLISHED:服务端收到ACK,完成建链;
SYN_SENT -> CLOSED:客户端等待超时,未收到ACK + SYN;
SYN_SENT -> ESTABLISHED:客户端收到ACK + SYN,发送ACK;
ESTABLISHED -> FIN_WAIT_1:A端调⽤close函数,发送FIN,主动关闭连接;
FIN_WAIT_1 -> FIN_WAIT_2:A端收到ACK;
FIN_WAIT_1 -> CLOSING:A端收到FIN,可能是B端同时调⽤了close函数,同时关闭连接;
FIN_WAIT_1 -> TIME_WAIT:A端收到SYN + ACK,回复ACK,表示B端主动建链;
FIN_WAIT_2 -> TIME_WAIT:A端收到FIN,回复ACK;
CLOSING-> TIME_WAIT:A 端 收 到 ACK;
TIME_WAIT-> CLOSED:A端等待2MSL超时;
ESTABLISHED -> CLOSE_WAIT:A端收到FIN,恢复ACK,表示关闭B端到A端连接;
CLOSE_WAIT -> LAST_ACK:A端发送FIN,表示关闭A端到B端连接;
注1:建链后,服务端对客户端请求的ACK是随着要写的数据⼀起发送的,该过程减少⼀次IO交互,称为捎带发送(piggybacking);捎带发送有时间窗⼝,如果超过该窗⼝,则独⽴发送ACK分组;
注2:关闭连接时,主动关闭的⼀端会经历TIME_WAIT状态,⽽被动关闭的⼀端会经历CLOSE_WAIT 状态;
时间窗口的意思是说,如果当时没有要发送的数据,ACK的发送不会等待太长时间(如果等待时间太长,客户端收不到ACK会超市重传),则独立发送ACK;
如果单独发送和接收⼀个分组,使⽤TCP协议需要⾄少8个分组(3次握⼿+4次挥⼿+1次发送),⽽使⽤UDP协议只需要2个分组(1个请求分组+1个应答分组)。可以看到使⽤UDP⽐使⽤TCP协议,交互过程数据量较少,故⽽性能更好,但也牺牲了可靠性;
1.7 TIME_WAIT状态
⾯试问题:TCP协议中的TIME_WAIT是什么状态?为什么要有该状态?
主动关闭连接的⼀端会经历TIME_WAIT状态,该状态会持续2MSL时⻓后,才变为CLOSED状态; TIME_WAIT建议值为2min,但通常为1~4min;
MSL(Maximum Segment Lifetime):最⻓分节⽣命周期,表示IP数据报能够在⽹络中存活的最⻓时间,超过该时间的IP数据报将被忽略;
跳限(hop limit):每个IP数据报中包含⼀个跳数限制,即该数据报在链路中最⼤可跨过的路由器数,超过该数量,IP数据报会被忽略;跳限字段为8位,故最⼤值为255;
迷途重复分组(lost duplicate)/ 漫游重复分组(wandering duplicate):由于路由异常,⽽徘徊在⽹络中的TCP分节,导致超时后,⼜重复发送了该分节,造成重复;
1)实现可靠的TCP全双⼯连接终⽌:最后⼀个ACK丢失后,可能需要重传,因⽽需要TIME_WAIT状态进⾏中转;
2)允许⽼的重复分节在⽹络中消逝:如果TCP连接断链后,⻢上⼜使⽤相同的IP和端⼝建⽴⼀个连 接,则新建连接有可能收到旧连接的报;为了防⽌这种情况的发⽣,需要在TIME_WAIT状态等待2MSL时⻓,以保证上⼀个连接的包全部消逝后,再启⽤新的连接;
1.8 连接端⼝号
TCP、UDP、SCTP协议,均有端⼝号的概念,都使⽤16位整数表示端⼝号范围;
不同协议之间的端⼝号不存在冲突,故可以同时开启TCP、UDP、SCTP的相同端⼝号;
与服务端指定端⼝建链时,客户端同样需要使⽤⼀个临时端⼝与服务端进⾏通信,该临时端⼝由协议 栈⾃动分配;
套接字对:⼀个TCP的通信链路,包含⼀对套接字(IP+端⼝),是定义两个连接端点的四元组(本地IP地址,本地TCP端⼝号,外地IP地址,外地TCP端⼝号);
1)0~1023,公共服务的端⼝号,⽐如ssh的端⼝号22;
2)1024~49151,⽤于登记开启的监听端⼝号,⽐如web服务的8080端⼝;
3)49152~65535,⽤于开启临时端⼝号,与服务端进⾏通信;
注:端⼝号的范围根据不同的OS可能不同,⼀般约定1024之前的端⼝为预留端口,不可以⾃由使⽤;
对于客户端⽽⾔在物理层面,由于⼀个Socket连接也被视作⼀个⽂件,故会占⽤⼀个⽂件句柄(客户端侧机器);
在逻辑层面,使⽤(协议,源IP,源端⼝,⽬标IP,⽬标端⼝)这个五元组来唯⼀标识⼀个连接,故能够开启的连接多少,取决于五元组中的组合有多少种。
理解误区:由于机器可以开启的端⼝范围总是⼩于65535的,因⽽容易理解为⼀台客户端机器上能够
建⽴到服务器的连接上限,即为可以开启的端⼝数。实际上,端⼝是逻辑概念,建⽴连接的数量,取 决于上述五元组中各个元素取值的组合。
问:假设有固定数量的客户端机器,想要发起上百万个连接,到同⼀个服务器,如何突破端⼝限制?
由于机器数量固定,故(协议,源IP,源端口,⽬标IP,目标端口)五元组中,协议、源IP、⽬标IP即已 固定。而对于同⼀个目标端口(服务器端口),同⼀个客户端机器能够开启的最⼤端口数不会超过65535个,因而想要发起上百万的连接,需要提供多个目标端口(服务器端口),每个端口承担6w多 个客户端连接,突破端口限制。
1.9 TCP数据发送过程(了解)
每个TCP套接字有⼀个发送缓冲区(只有发送缓冲区满了,才会发送数据(如果一个字节一个字节的发送数据,效率较低);就好像往池子里灌水,一瓢一瓢的灌比一滴一滴的灌效率更高),通过SO_SNDBUF选项设置;数据的发送过程如下:
1)TCP层:当应⽤调⽤write时,内核从该应⽤进程的缓冲区中复制所有数据写到套接字的发送缓冲区 中;
2)TCP层:若发送缓冲区⽆法存放全部数据时,则将应⽤进程置于休眠状态,对于阻塞IO,内核将不 从write系统调⽤中返回,直到发送缓冲区腾出空间,应⽤进程所有数据都拷⻉到发送缓冲区中;
注:仅当收到对端的ACK之后,才能够不断清理发送缓冲区中已确认的数据;
3)TCP层:本端TCP以MSS⼤⼩或者更⼩的块,把数据传递给IP层;每个数据块上有⼀个TCP头(20字节);(MSS值由对端MSS选项传递)
4)IP层:给TCP分节安装⼀个IP头,组成IP数据报,并按照⽬的IP地址查找路由表,确定外出接⼝; 之后把数据发送给相应的数据链路,期间IP层可能会对IP数据报分为多个分⽚发送;
5)数据链路层:每个数据链路维护⼀个输出队列,如果队列已满,则新到分组会被丢弃,并沿着协议 栈向上返回错误;TCP层捕获该错误,并尝试重传相应分节;该过程并不会被上层应⽤感知;
注:⼀次write系统调⽤成功返回,仅表示发送缓冲区可以复⽤,并不表示对端已经接收到发送的数据;
1.10 超时重传和快速重传
超时重传(Timeout Retransmission)和快速重传(Fast Retransmission)是在计算机⽹络中⽤于处
超时重传(Timeout Retransmission)是指发送⽅在发送数据包后设置⼀个定时器,如果在规定的时间内没有收到确认(ACK)或者重复确认(Duplicate ACK),发送⽅会认为该数据包丢失,然后重新发送该数据包。这种机制基于超时的假设,即数据包丢失的原因可能是⽹络拥塞、传输延迟等。超时重传的缺点是它需要等待超时时间才能重传数据包,这会导致⽹络传输效率低下。
行为:如果在超时时间内没有接收到确认,发送⽅会假设该数据包丢失,然后重新发送该数据包。
触发条件:超时重传通常发⽣在⽹络拥塞或传输延迟导致数据包丢失的情况下。
快速重传(Fast Retransmission)是⼀种基于接收⽅的反馈机制的重传机制。当发送⽅发送⼀个数据包后,接收⽅会发送确认(ACK)给发送⽅,表示已经成功接收到该数据包。但是,如果接收⽅收到了⼀个不按顺序的数据包(例如,接收⽅已经收到了数据包5,但是却未收到数据包3,此时会重复确认数据包4,连发3次数据包4后,发送端重传数据包3),接收⽅会发送⼀个重复确认(Duplicate ACK)给发送⽅,指示发送⽅某个数据包丢失。当发送⽅连续收到3次重复确认时,它会⽴即重传相应的数据包,⽽不必等待超时时间。这样可以快速恢复丢失的数据包,提⾼⽹络传输效率。
原理:接收⽅在收到⼀个乱序的数据包后,会发送重复确认(Duplicate ACK)给发送⽅。
行为:发送⽅在连续收到⼀定数量的重复确认时(通常是3个),⽴即重传对应的数据包,⽽不必等待超时。
触发条件:快速重传通常发⽣在⽹络丢包引起数据包乱序的情况下。接收⽅通过发送重复确认来指示发送⽅某个数据包丢失。
总结来说,超时重传是在发送⽅设置的定时器超时后重新发送数据包,⽽快速重传是在接收⽅发送重复确认后⽴即重传数据包。这两种重传机制在不同的情况下使⽤,以提⾼数据传输的可靠性和效率。
1.11 TCP Header结构
使⽤ping()估算TCP数据传输时间,⼀次ping()使⽤84字节的IP数据报;
假设30次ping()测量的平均RTT时⻓为175ms,且要发送2000字节数据,每次发送40字节,则⼀共发送50次;
每次发送时,除了40字节数据,还包含 20字节的IP Header,20字节的TCP Header,⼀共80字节; 则可以估算发送这2000字节的⼤概耗时为:175ms * 50次 = 8750ms;
1.12 TCP可靠传输
对于⽹络中的两个节点通信,中间要经过很⻓的链路,期间可能存在很多问题,因⽽我们认为直接在⽹络中传输数据是不可靠的。
所谓可靠,就是数据能够正常、完整、有序的被对端收到。TCP协议依靠如下机制,实现可靠通信:
在TCP(传输控制协议)的可靠传输中,有两个重要的机制:重排(reordering)和窗口(window)。
重排指的是网络中的数据包可能以非顺序的方式到达接收方。这可能是由于网络拓扑、路由选择、拥塞等原因造成的。TCP使用序列号来标识发送的数据包,接收方根据序列号来恢复数据的正确顺序。
当接收方收到乱序的数据包时,它会将这些数据包缓存起来,然后按照序列号对它们进行排序,以确保数据包按正确的顺序交付给上层应用程序。TCP使用接收窗口来管理乱序数据包的缓存和排序。
窗口机制是TCP中的流量控制和拥塞控制的基础。发送方和接收方都有一个窗口大小(window size)的概念。
发送方的窗口大小表示可以发送但尚未收到确认的数据量。发送方根据接收方发送的确认信息来动态调整窗口大小,以控制发送的速率,避免发送过多的数据导致接收方无法及时处理。
接收方的窗口大小表示它能够接收的数据量。接收方通过发送窗口大小信息给发送方,告知发送方它目前的接收能力。发送方根据接收方的窗口大小来控制发送的速率,以避免发送过多的数据导致接收方缓冲区溢出。
窗口机制使得发送方和接收方能够协调数据传输的速率,以适应网络的状况和接收方的处理能力,从而实现可靠的数据传输。
综上所述,TCP通过重排机制和窗口机制来实现可靠传输。重排机制确保接收方能够正确排序乱序的数据包,窗口机制用于流量控制和拥塞控制,确保发送方和接收方之间的数据传输能够合理、高效地进行。
ARQ(Automatic Repeat Request)协议是⼀种⽤于可靠数据传输的协议,位于传输层。它是在数据通信中处理和纠正传输错误和丢失数据的⼀种机制。
ARQ协议的主要⽬标是确保数据的可靠传输,通过引⼊ACK确认和超时重传机制 实现这⼀⽬标:
1)停等 ARQ(Stop-and-Wait ARQ):发送⽅发送⼀个数据包,然后停⽌等待接收⽅的确认。只有在接收到确认后,发送⽅才发送下⼀个数据包。
2)连续 ARQ(Continuous ARQ):发送⽅连续发送多个数据包⽽不等待每个数据包的确认。接收⽅收到数据包后,发送累积确认,指示已成功接收到⼀系列数据包。如果发送⽅未收到确认或收到确认指示有错误,它将重传相应的数据包。(类似pipeline)
- Go-Back-N:在接收⽅发现错误或数据包丢失时,发送⽅会重新发送整个窗⼝中未确认的数据包。
- Selective-Repeat(选择重传):在接收⽅发现错误或数据包丢失时,发送⽅只会重传具有问题的数据包,⽽不是整个窗⼝中的所有数据包。
3)反馈 ARQ(Feedback ARQ):接收⽅会周期性地发送确认消息,以指示已成功接收到的数据包。发送⽅会根据接收到的确认信息进⾏重传处理。
注1:停等 ARQ需要逐条处理消息的请求-响应,可能产⽣性能问题,因⽽较少被采⽤;
注2:kafka在应⽤层确保消息传递⼀致性时,也使⽤了类似 Continuous ARQ 和 Feedback ARQ 的实现机制;
1)发送⽅对接收⽅发送数据包,然后等待接收⽅回复ACK并且开始计时;
3)当数据包没有成功被接收⽅接收,接收⽅不会发送ACK。发送⽅在等待⼀定时间后,重新发送数据包;
为了克服停等 ARQ 协议⻓时间等待ACK的缺陷,连续 ARQ 协议会连续发送⼀组数据包,然后再等待这些数据包的ACK。
发送⽅和接收⽅都会维护⼀个数据帧的序列,这个序列被称作窗⼝。发送⽅的窗⼝⼤⼩由接收⽅确定,⽬的在于控制发送速度,以免接收⽅的缓存不够⼤,⽽导致溢出,同时控制流量也可以避免⽹络 拥塞。协议中规定,对于窗⼝内未经确认的分组需要重传。
回退N步协议允许发送⽅在等待超时的间歇,可以继续发送分组。所有发送的分组,都带有序号。在Go-Back-N协议中:
1)上层业务发送数据,调⽤send()时,发送⽅⾸先要检查发送窗⼝是否已满;
2)发送⽅接收ACK:在该协议中,对序号为n的分组的确认采取累积确认的⽅式,表明接收⽅已正确接收到序号n以前(包括n)的所有分组;
3)发送⽅等待超时:若出现超时,发送⽅将重传所有已发出但还未被确认的分组;发送⽅在发完⼀个窗⼝⾥的所有分组后,会检查最⼤的有效确认,然后从最⼤有效确认的后⼀个分组开始重传;
1)若⼀个序号为n的分组被正确接收,并且符合顺序,则接收⽅会为该分组回复⼀个ACK,并将该分组交由上层业务 处理;否则,丢弃分组;
2)若分组n已被接收并且交由上层业务处理,则说明⽐n⼩的所有分组均已正确接收并交付处理;
比如:发送方一次性发送了序号为:1、2、3、4、5的分组,如果序号为2的分组丢失,即便序号为3、4、5的分组都被正确接收(但是不符合接收顺序),发送方依然会重传2、3、4、5分组;
Go-Back-N采⽤的技术包括:序号、累积确认、检验以及超时重传等;
缺点:Go-Back-N改善了停等协议中等待时间较⻓的问题,但仍然存在性能问题:当窗⼝很⼤时,如果发⽣重传,则增加了重发消息的区间,会⼤⼤降低效率;
相⽐于Go-Back-N协议,Selective-Repeat协议通过让发送⽅仅重传在接收⽅丢失或损坏了的分组,从⽽避免了不必要的重传,从⽽提⾼效率。
在Selective-Repeat协议下,发送方需响应以下三种事件:
1)从上层收到数据。当从上层收到数据后,发送⽅需检查下⼀个可⽤于该分组的序号。若序号在窗⼝中则将数据发送;
- 若收到ACK,且该分组在窗⼝内,则发送⽅将那个被确认的分组标记 为已接收;
- 若该分组序号等于基序号,则窗⼝序号向前移动到具有最⼩序号的未确认分组处;
- 若窗⼝移动后并且有序号落在窗⼝内的未发送分组,则发送这些分组;
假设接收窗⼝的基序号为4,分组⻓度也为4;接收⽅需响应以下三种事件:
- 若收到的分组落在接收⽅的窗⼝内(序号在 (4, 7] 区间),将发送⼀个ACK;
- 若该分组是以前没收到的分组(序号⼩于4),则被缓存;
- 若该分组的序号等于基序号4,则该分组以及以前缓存的序号连续的分组都交付给上层,然后,接收窗⼝将向前移动。
2)序号在[0,3]内的分组被正确接收。在该情况下,必须产⽣⼀个ACK,尽管该分组是接收⽅以前已确认过的分组。若接收⽅不确认该分组,发送⽅窗⼝将不能向前移动。
对于接收⽅来说,若⼀个分组正确接收⽽不管其是否按序,则接收⽅会为该分组返回⼀个ACK给发送⽅。失序的分组将被缓存,直到所有丢失的分组都被收到,这时才可以将⼀批分组按序交付给上层,并向前滑动接收窗⼝;
⽐如:上⾯图示中,序号为2的分组丢失,则接收⽅每次收到消息后,回复已确认的最⼤ACK 1;发送⽅收到ACK后,重发分组2;接收⽅收到分组2后,向前滑动接收窗⼝,返回ACK5;此时[0, 5]区间的消息已经全部正常接收,并可以处理;
TCP是基于ARQ协议的,它使⽤了ARQ的确认和重传机制来实现可靠的数据传输。TCP协议使⽤了⼀种ARQ协议的变体;在TCP中,发送⽅将数据分割成⼩的数据段,并使⽤ARQ机制确保它们的可靠传输。发送⽅会等待接收⽅的确认,并在需要时进⾏重传。接收⽅会对接收到的数据进⾏校验,并发送 确认或请求重传的消息。
RTT(Round-Trip Time):往返时延。表示从发送端发送数据开始,到发送端收到接收端的确认(假设接收端收到数据后便⽴即发送确认),总共经历的时延; 由三部分组成:
- 链路的传播时间(propagation delay);(链路传播时间(Link propagation time)是指信号在物理链路上传播所需的时间。它是从信号从发送端发送出去到达接收端的时间延迟。)
- 末端系统的处理时间;(末端系统处理时间(End-system processing time)是指在网络通信中,数据到达接收端的末端系统后,经过处理和操作所需的时间延迟。)
- 路由器缓存中的排队和处理时间(queuing delay);(在路由器的缓存中,排队和处理时间是指数据包在进入路由器后等待被处理和转发的时间延迟。)
其中,前两个部分的值对于⼀个TCP连接相对固定,路由器缓存中的排队和处理时间会随着整个⽹络 拥塞程度的变化⽽变化。 所以RTT的变化在⼀定程度上反应⽹络的拥塞程度。
RTO(Retransmission TimeOut):重传超时时间;超时重传时间,根据RTT动态调整,由协议栈⾃动控制;⼀般RTO⾄少为1.5倍RTT;RTO过⼩,则可能过于频繁的发起重传;RTO过⼤,则重传等待的时间可能过⻓;
1.13 TCP流量控制
双⽅在通信的时候,发送⽅的速率与接收⽅的速率不⼀定相等,如果发送⽅的发送速率太快,会导致接收⽅处理不过来,这时候接收⽅只能把处理不过来的数据存在缓存区⾥(失序的数据包也会被存放在缓存区⾥);如果缓存区已满,发送⽅还在发送数据,接收⽅只能把收到的数据包丢掉;⼤量的丢包会极⼤浪费⽹络资源,因此,我们需要控制发送⽅的发送速率, 让接收⽅与发送⽅处于⼀种动态平衡才好; 对发送⽅发送速率的控制,称之为流量控制。
接收⽅每次收到数据包后,可在发送ACK时,同时告诉发送⽅⾃⼰的缓存区还剩多少空间。我们也把 缓存区的剩余空间⼤⼩称之为接收窗口⼤⼩,⽤变量win来表示。
发送⽅收到之后,便会调整⾃⼰的发送速率,也就是调整⾃⼰发送窗⼝⼤⼩,当发送⽅收到的接收窗口的⼤⼩为0时,发送⽅就会停⽌发送数据,防⽌⼤量丢包;
上述过程即为TCP的负反馈机制:通过接收端的反馈,决定发送端的速率;
注:接收端⽆法直接主动告知发送端⾃⼰的接收窗⼝⼤⼩,但通过发送窗⼝和接收窗⼝的动态调整,接收端可以间接地影响发送端的发送速率,实现流量控制。
问1:若发送端因接收窗口为0⽽停⽌发送数据后,如何判断是否可以再次发送数据?
1)当发送⽅收到接受窗口 win = 0 时,则停⽌发送报⽂,并且同时开启⼀个定时器,每隔⼀段时间向
2)接收⽅收到报⽂后,通过ACK反馈当前接收窗口 win 的⼤⼩;
不是,根据边际收益递减规律,当接收窗⼝达到某个值的时候,再增⼤的话也不怎么会减少丢包率的 了,⽽且还会消耗内存。所以接收窗⼝的⼤⼩必须根据⽹络环境以及发送发的的拥塞窗口来动态调整。
不⼀定相等,接收⽅在发送ACK报⽂的时候,会告诉发送发⾃⼰的接收窗口⼤⼩,⽽发送⽅的发送窗口会据此来设置⾃⼰的发送窗口,但并不⼀定相等;因为接收⽅把ACK报⽂发出去的那⼀刻,就已经 在⼀边处理堆在⾃⼰缓存区的数据了,所以⼀般情况下接收窗⼝ >= 发送窗口。
1.14 TCP拥塞控制
假设主机A给主机B传输数据。两台主机在传输数据包的时候,如果发送⽅迟迟没有收到接收⽅反馈的ACK,那么发送⽅就会认为它发送的数据包丢失了,进⽽会重新传输这个丢失的数据包。
然⽽实际情况有可能此时有太多主机正在使⽤信道资源,导致网络拥塞了,⽽A发送的数据包被堵在了半路,迟迟没有到达B。这个时候A误认为是发⽣了丢包情况,会重新传输这个数据包。
结果就是不仅浪费了信道资源,还会使⽹络更加拥塞。因此需要进⾏拥塞控制。
A与B建⽴连接之后,就可以向B发送数据了,然⽽这个时候A并不知道此时的⽹络拥塞情况如何,此时 A不知道⼀次性连续发送多少个数据包。
拥塞窗口:把A⼀次性连续发送多少个数据包称之为拥塞窗⼝,⽤ N 代表此时拥塞窗⼝的⼤⼩; 为了探测⽹络的拥塞情况,可以采取2种策略:
1)线性增⻓:先发送⼀个数据包试探下,如果该数据包没有发⽣超时(没有丢包)。则下次发送时就发送2个,如果 还是没有发⽣超时事件,下次就发送3个,以此类推,即N = 1, 2, 3, 4, 5.....
2)指数增⻓:⼀个⼀个增加实在是太慢了,所以可以刚开始发送1个,如果没有发⽣超时,就发送2个,如果还是没有发送超时事件就发送4个,接着8个...,⽤翻倍的速度类推,即 N = 1, 2, 4, 8, 16...
缺点:⽆论是第⼀种⽅法还是第⼆种⽅法,最后都会出现瓶颈值。但第⼀种情况的增⻓速率过慢,可
能很慢到达瓶颈值;⽽第⼆种情况增⻓速度过快,可能很快到达瓶颈值;
为了解决探测过慢或过快的问题,可以把第⼀种⽅法和第⼆种⽅法结合起来:刚开始使⽤指数增⻓, 增⻓到某⼀个阈值(记为ssthresh)后,就改为线性增⻓。我们把指数增⻓阶段称之为慢启动,线性增⻓阶段称之为拥塞避免;
图1 慢启动
随着拥塞窗口的增加,发送速率不断提高,当TCP遇到分组超时重传时,即认为发生了网络拥塞;
1)此时将更新ssthresh的值为当前拥塞窗口的一半,上图中是更新为24的一半即12;
2)更新cwnd的值为1;
3)然后继续执行慢启动—拥塞避免,如上图所示;
如果TCP发送方接收到连续的3个重复确认,则认为是正常的网络包丢失,而不是网络拥塞造成的,这正是快恢复算法的功劳;
1)重传丢失的分组;
2)执行快恢复算法;
图2 拥塞避免
(4)什么是快速恢复?
发⽣超时事件,不⼀定是⽹络出现了拥堵。也有可能是因为某个数据包出现了丢失或者损坏。如果视作拥塞控制,从最初状态开始,则可能导致控制较为严格,降低发送速率;
为了上述情况,我们通过冗余ACK来处理:即连续3次收到重复确认,表明数据包丢失了,可以快速重 传丢失的数据包;
假设A给B发送M1, M2, M3, M4, M5...N个数据包,如果B收到了M1, M2, M4... 却始终没有收到M3,这个时候就会重复确认M2,意在告诉A,M3还没收到,可能是丢失了。
当A连续收到了三个确认M2的ACK,且M3超时事件还没发⽣。A就知道M3可能丢失了,这个时候A就不必等待M3设置的计时器到期了,⽽是快速重传M3。并且调整 ssthresh = MAX / 2,但是这个时候并⾮把控制窗⼝ N 重置为1,⽽是直接让 N = ssthresh,并线性增⻓。该过程称为快速恢复,具有快速恢复的TCP版本称之为TCP Reno。
图3 快恢复
注:另外⼀种TCP版本,⽆论是收到三个相同的ACK还是发⽣超时事件,都把拥塞窗⼝的⼤⼩设为1, 从最初状态开始,这种版本称为TCP Tahoe。
1.15 TCP/IP 协议栈报⽂格式举例
Address Resolution Protocol,地址解析协议,把IPv4地址映射成⼀个硬件地址(MAC地址),⽤于
(5)ICMP协议(网络层)
Internet Control Message Protocol,⽹络控制消息协议,处理主机和路由之间的消息通信;
如果需要本文 WORD、PDF 相关文档请在评论区留言!!!
如果需要本文 WORD、PDF 相关文档请在评论区留言!!!
如果需要本文 WORD、PDF 相关文档请在评论区留言!!!
来源地址:https://blog.csdn.net/weixin_47156401/article/details/132780015