引言
TCP/IP协议是互联网和许多现代网络通信的基础。它提供了一套标准化的通信协议,使得不同设备和系统能够在同一网络上互相通信。本文将详细介绍TCP/IP协议的各个方面,帮助读者理解其工作原理和应用场景。
TCP/IP协议与OSI七层模型对应关系
各层的作用
层级 | 作用 |
---|---|
应用层 | 应用层协议包括HTTP(超文本传输)、FTP(文件传输)、SMTP(电子邮件)、DNS(域名解析)等协议。 |
表示层 | 信息的语法语义以及它们的关联,如加密、解密、转换翻译、压缩解压缩。 |
会话层 | 不同机器上的用户之间建立及管理会话。 |
传输层 | 接受上一层的数据,在必要的时候路把数据进行分割,并将这些数据交给网络层,并且保证这些数据段可靠、有序的到达目的地。传输层主要有两个协议:TCP传输控制协议、UDP用户数据报协议。 |
网络层 | 控制子网的运行,如逻辑编址、分组传输、路由选择。简单来说就是,网络层负责将数据传输到目标地址,目标地址可以是多个网络通过路由器连接而成的某一个地址,网络层的作用就是在复杂的路径中找到一条合适的路径将数据通过这条路径发送给对方。 |
数据链路层 | 处理物理寻址和数据帧传输。 |
物理层 | 机械、电子、定时接口通信信道上的原始比特流传输。 |
TCP/IP协议特点
- 面向连接:TCP协议在传输数据前需要建立连接,确保数据传输的可靠性。例如,网页浏览需要在浏览器和服务器之间建立TCP连接。
- 全双工通信:TCP连接建立后,双方可以同时发送和接收数据。例如,视频通话过程中,双方可以同时发送和接收音视频数据。
- 可靠性:TCP协议通过确认应答、重传机制和序号保证数据不丢失、无差错、不重复和按序到达。例如,文件传输需要确保文件完整性,TCP协议可以保证这一点。
- 面向字节流:TCP协议将数据视为连续的字节流进行传输。例如,下载文件时,TCP协议将文件数据视为连续的字节流,确保数据顺序接收。
报文段格式
- TCP虽面向字节流,但传输的数据单元是报文段
- 报文段=首部+数据
标志位的含义
标记 | 含义 |
---|---|
URG | Uregent:紧急位,URG=1,表示数据紧急,需要立即处理。 |
ACK | Acknowledgement:确认位,ACK=1,确认号才生效,用于确认已收到的数据。 |
PSH | Push:推送位,PSH=1,尽快将数据交付给应用层,而不是等待缓冲区满。 |
RST | Reset:重置位,RST=1,重新建立连接,用于异常情况下重置连接。 |
SYN | Synchronization:同步位,SYN=1,表示连接请求报文,当SYN=1而ACK=0时,表明这是一个连接请求报文,若对方同意建立连接,则在相应报文中令SYN=1和ACK=1。 |
FIN | Finish:终止位,FIN=1,表示释放连接,用于正常关闭连接。 |
建立连接过程
建立连接前客户端、服务器都处于关闭状态(CLOSED),直到客户端主动打开连接,服务器才被动打开连接(处于监听状态LISTEN),等待接受客户端的请求。
1、第一次握手:将同步标志位设为1(SYN=1),随机选择一个序号(seq=x)。客户端进入SYN_SEND状态。
2、第二次握手:服务器收到请求连接报文段后,若同意建立连接,则将同步标志位设为1(SYN=1),确认标记为设为1(ACK=1),随机选择一个序号(seq=y),确认收到的序号(ack=x+1),服务器进入同步已接收状态(SYN_RCVD)。
3、第三次握手:客户端收到确认报文段后,向服务器再次发出连接确认报文段,确认标记位设为1(ACK=1),序号(seq=x+1),确认收到的序号(ack=y+1)。客户端先进入ESTABLISHED状态,服务端收到后同时进入。
为什么建立连接需要三次握手,两次行不行?
三次握手是为了确定客户端、服务器收发数据都正常。防止服务器接收了早已失效的连接请求,从而一直等待客户端请求,最终导致浪费资源。如果只有两次握手,就会出现,客户端发出的第一个连接请求段没有丢失,只是在某个网络节点长时间滞留,而客户端进入了超时重传,重新发送了一个连接请求,建立连接,传输完数据之后连接释放,而此时第一次发送的连接请求到达服务器,这是一个失效的连接请求,但是服务器不知道,正常确认连接,此时客户端已经关闭,服务器一直等待。所以两次不行。
1、第一次握手:客户端发送请求,此时服务器知道客户端发送数据正常。
2、第二次握手:服务器发送确认,此时客户端知道服务器接收、发送数据都正常。
3、第三次握手:客户端发送确认,此时服务器知道客户端接收数据正常。
如果已经建立连接,但是客户端突然出现故障怎么办?
TCP还设有一个保活计时器,Client端如果出现故障,Server端不能一直等下去,这样会浪费系统资源。每收到一次Client客户端的数据帧后,Server端都的保活计时器会复位。计时器的超时时间通常是设置为2小时,若2小时还没有收到Client端的任何数据帧,Server端就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,Server端就认为Client端出了故障,接着就关闭连接。
释放连接过程
1、第一次挥手:客户端(服务器也可以主动发,一般是客户端)向服务器发送一个断开连接请求报文,FIN=1、seq=u。发送完成后,进入FIN_WAIT-1(终止等待1)状态。这表示客户端没有业务数据要发给对方了,通知服务器自己要断开连接了。
2、第二次挥手:正常情况下,在收到客户端发送的FIN断开连接请求之后,服务器都会发送一个ACK响应报文,ACK=1、seq=v、ack=u+1。该报文的意思是,我同意你的断开连接请求,服务器进入CLOSEWAIT(关闭等待)状态,此时TCP协议服务会通知高层的应用进程,对方已经没有数据要发送了,如果我方还有数据要发送,可以继续发。客户端进入FIN_WAIT-2(终止等待状态2)。
3、第三次握手:在发送完ACK确认报文后,服务器还能继续发送业务数据,当服务器发送完数据后,或者CLOSEWAIT(关闭等待)截止后,服务器会主动发送断开连接请求,FIN=1、ACK=1、seq=w、ack=u+1。表示服务器也没有数据要发送了,然后进入LAST_ACK(最后确认)状态。
4、第四次挥手:客户端在收到服务器的断开连接请求报文后,进行最后的确认,向服务器发送一个ACK确认报文,然后进入TIME_WAIT(超时等待状态),在等待2MSL的时间后,如果期间没有收到其他报文,则证明对方已正常关闭,主动断开方的连接最终关闭。
最后为什么要等待2MSL之后才关闭,为什么不收到对方关闭请求之后就关闭?
因为最后一次的确认报文有可能丢失,如果服务器超时等待没有收到确认报文,会在发一次,此时如果客户端直接断开连接,那服务器一直没得到响应,会一直发,浪费资源。2MSL对应于一次消息的来回(一个发送和一个回复)所需的最大时间。如果直到2MSL,主动断开方都没有再一次收到对方的报文(如FIN报文),则可以推断ACK已经被对方成功接收,此时,主动断开方将最终结束自己的TCP连接。
为什么关闭连接需要四次挥手,而建立连接只需要三次握手?
关闭连接时,被断开放在接收到对方的FIN断开连接请求报文时,很可能还有业务数据没发送完成,并不能马上断开连接,又不能对对方的断开连接请求置之不理,因为对方没有收到确认会认为断开连接请求在路上丢失,触发超时重传。所以只能先回复一个ACK确认报文,告诉对方,我知道你要断开连接了,但我有业务数据要发送,只能等待我所有的业务数据都发送完才能真正结束,在结束之后,我会给你发送FIN+ACK断开连接请求报文的。所以被断开方的确认报文需要分成两步,故需要四次挥手。
在建立连接的时候,只需要确认双方都能收发数据。
实现可靠传输
1、滑动窗口
-
发送窗口:发送方维持的一组连续的、允许发送帧的帧序号(大致分为四组,一组是已经发送并被确认的分组,一组是已经发送但还没有被确认的分组,一组是即将要发送的分组,一组是还没轮到要发送的分组,滑动窗口控制已经发送但没被确认和马上要发送的分组,当已经发送的数据被确认,窗口开始滑动,将没轮到的分组纳入滑动窗口。滑动窗口的最大尺寸由发送方设定,接收方收到数据包之后,会发送一个确认报文给发送方,发送方收到确认报文后会将滑动窗口移动)。主要对发送方进行流量控制。
-
接收窗口:接收方维持的一组连续的、允许接收帧的帧序号。控制可接收哪些帧数据&不可接收哪些帧数据。当收到数据帧后,将窗口向前移动一个位置,并发回确认帧,若收到的数据帧落在接收窗口之外,则一律丢弃。
2、重传机制
- 超时重传:每当发送一个数据包时,发送方会启动一个超时计时器。如果在规定时间内没有收到接收方的确认应答(ACK),则认为该数据包丢失,需要重新发送。
- 快速重传:如果发送方连续收到三个重复确认应答,则认为该数据包可能丢失,不必等待超时计时器到期,立即重传该数据包。
3、流量控制
接收方根据自己接收缓存的大小,动态调整发送方发送窗口的大小,从而控制发送方的发送速率,避免出现发送方和接收方速度不匹配的问题。即发送方发送的太快,接收方来不及接收,发送方触发超时重传,恶性循环。
从上图可知接收方进行了两次流量控制,第一次把窗口减少到rwnd=300,第二次直接减少到了0,即不允许发送方再发送数据了。
4、拥塞控制
防止过多的数据注入到网络中,使得通信网络链路过载
1、慢开始:在新连接建立或网络拥塞发生后的初始阶段,通过逐步增加拥塞窗口(cwnd)的大小来探测网络容量,避免网络突然过载。
- 初始阶段:拥塞窗口(cwnd)设置为一个较小的值(通常为1个最大报文段,MSS)。
- 指数增长:每次收到一个ACK,cwnd增加1个MSS。这样,cwnd呈指数增长。
- 阈值:当cwnd达到一个阈值(ssthresh)时,慢启动阶段结束,进入拥塞避免阶段。
2、拥塞避免:拥塞避免算法在慢开始后期或网络已趋于稳定时,通过线性增长cwnd来防止网络拥塞。
- 线性增长:每个RTT(往返时间)周期内,cwnd增加一个MSS(即每次收到一个ACK,cwnd增加1/cwnd)。
- 拥塞检测:如果检测到网络拥塞(通过超时或快速重传),ssthresh被设置为当前cwnd的一半,进入慢启动或快速恢复阶段。
3、快重传:接收方每收到一个失序的报文段后 就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方),而不要等到自己发送数据时才进行捎带确认。发送方只要一连收到3个重复确认就立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器到期。
4、快恢复:快速恢复算法在快速重传后立即调整拥塞窗口,使得网络迅速恢复到稳定状态。
- 把慢开始门限设置为出现拥塞时发送方窗口值的一半 = 拥塞窗口的1半。由于跳过了拥塞窗口(cwnd)从1起始的慢开始过程,所以称为:快恢复。此处网络不会发生网络拥塞,因若拥塞,则不会收到多个重复确认报文。
参考文章:https://cloud.tencent.com/developer/article/1963303
参考文章:https://blog.csdn.net/Royalic/article/details/119985591