TCP报文结构/三次握手/四次挥手/滑动窗口/拥塞控制

网络分层模型

OSI七层模型

OSI 七层协议实现起来过分复杂,而且运行效率很低;制定标准的周期太长,当OSI 国际标准制定出来时,基于 TCP/IP 的互联网已经抢先在全球相当大的范围成功运行了。OSI 七层模型虽然失败了,但是却提供了很多不错的理论基础。为了更好地去了解网络分层,OSI 七层模型还是非常有必要学习的。

  • 应用层
  • 表现层
  • 会话层
  • 传输层
  • 网络层
  • 数据链路层
  • 物理层

TCP/IP四层协议

  • 应用层
  • 传输层
  • 网络层
  • 网络接口层

TCP

TCP报文首部

TCP报文结构/三次握手/四次挥手/滑动窗口/拥塞控制_第1张图片 

  • 源端口和目的端口,各占2个字节;
  • 序号seq,占4个字节,假设主机A和主机B进行TCP通信,A发送给B的第一个TCP报文段中,序号值被系统初始化为某个随机值ISN(Initial Sequence Number,初始序号值)。那么在该传输方向上(从A到B),后续的TCP报文段中序号值将被系统设置成ISN加上该报文段所携带数据的第一个字节在整个字节流中的偏移。例如,某个TCP报文段传送的数据是字节流中的第1025~2048字节,那么该报文段的序号值就是ISN+1025.另外一个传输方向(从B到A)的TCP报文段的序号值也具有相同的含义;
  • 确认号ack,占4个字节,用作对另一方发送来的TCP报文段的响应。其值是收到的TCP报文段的序号值加1。假设主机A和主机B进行TCP通信,那么A发送出的TCP报文段不仅携带自己的序号,而且包含对B发送来的TCP报文段的确认号。反之,B发送出的TCP报文段也同时携带自己的序号和对A发送来的报文段的确认号;
  • 数据偏移,占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远;
  • 保留,占6位,保留今后使用,但目前应都位0;
  • 紧急URG,当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据;
  • 确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
  • 推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1;
  • 复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;
  • 同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;SYN报文不能携带数据/ACK报文可以携带数据。
  • 终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;
  • 窗口大小,占2字节,用于告诉发送方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度;
  • 检验和,占2字节,校验首部和数据这两部分;
  • 紧急指针,占2字节,指出本报文段中的紧急数据的字节数;
  • 选项,长度可变,定义一些其他的可选的参数。

建立TCP链接三次握手

初始:服务端LISTEN状态

  • 客户端:发送带有 SYN 标志的数据包(SYN=1,seq=x)进入【SYN-SENT】状态
  • 服务端:发送带有 SYN/ACK 标志的数据包(SYN=1 & ACK=1,ack=x+1 & seq=y)进入【SYN-RCVD】状态
  • 客户端:发送带有带有 ACK 标志的数据包(ACK=1,seq=x+1 & ack=y+1)进入【ESTABLISHED】已建立连接状态

当服务器收到客户端的确认后也进入【ESTABLISHED】状态,此后双方就可以开始通信了。

为什么要三次握手?

三次握手的目的是建立可靠的通信信道,就是双方确认自己与对方的发送与接收是正常的。

第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常

第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常

第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常

所以三次握手就能确认双方收发功能都正常,缺一不可。

断开TCP链接四次挥手

  • 客户端:发送一个 FIN,用来关闭客户端到服务器的数据传送(FIN=1,seq=x)【FIN-WAIT-1】
  • 服务器:收到这个 FIN,它发回一个 ACK(ACK=1,ack=x+1,seq=y),然后继续发送为发完的数据【CLOSE-WAIT、FIN-WAIT-2】
  • 服务器:剩余数据发送完毕,向客户端发送连接释放报文,发送一个 FIN 给客户端(FIN=1,seq=m)【LAST-ACK】
  • 客户端:发回 ACK 报文确认,并将确认序号设置为收到序号加 1【TIME-WAIT】,2*MSL后客户端CLOSED

1.客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。

2.服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

2.客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

3.服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

4.客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2*MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

4.服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

为什么客户端最后还要等待2MSL?

保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。

为什么建立连接是三次握手,关闭连接确是四次挥手呢?

建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。

而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。

如果已经建立了连接,但是客户端突然出现故障了怎么办?

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

TCP保证可靠传输的方式

连序确超校流拥

  1. 连接管理:连接管理就是三次握手与四次挥手的过程,保证可靠的连接,是保证可靠性的前提。
  2. 校验和: 在数据传输的过程中,将发送的数据段都当做一个16位的整数。将这些整数加起来。并且前面的进位不能丢弃,补在后面,最后取反,得到校验和。目的是检测数据在传输过程中的任何变化。如果收到段的校验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
  3. 序列号: TCP 给发送的每一个包进行编号;序列号的作用不仅仅是应答的作用,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据。
  4. 确认应答和超时重传:接收方收到数据后,都会对传输方进行确认应答,也就是发送ACK报文,报文中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。当 TCP 发出一个段后,它会等待一段时间,等待目的端收到这个报文段返回确认。如果不能及时收到一个确认,将重发这个报文段。在Linux中超时以500ms为一个单位进行控制,每重试一次x2,重试多次还未收到确认,TCP就认为网络或者对端出现异常,强制关闭连接。(类似ARQ协议)
  5. 流量控制: TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP根据接收端对数据的处理能力,决定发送端的发送速度。
  6. 拥塞控制: 当网络拥塞时,减少数据的发送。

ARQ自动重传请求

自动重传请求(Automatic Repeat-reQuest,ARQ)是OSI模型中数据链路层的错误纠正协议之一。它包括停止等待ARQ协议和连续ARQ协议,错误侦测、正面确认、逾时重传与负面确认继以重传等机制。

传统自动重传请求分成为三种:停等式(stop-and-wait)ARQ,回退n帧(go-back-n)ARQ,以及选择性重传(selective repeat)ARQ。后两种协议是滑动窗口技术与请求重发技术的结合,由于窗口尺寸开到足够大时,帧在线路上可以连续地流动,因此又称其为连续ARQ协议。三者的区别在于对于出错的数据报文的处理机制不同。三种ARQ协议中,复杂性递增,效率也递增。除了传统的ARQ,还有混合ARQ(Hybrid-ARQ)。

  • 停等式ARQ: 在停等式ARQ中,发送窗口和接收窗口大小均为1,发送方每发送一帧之后就必须停下来等待接收方的确认返回,仅当接收方确认正确接收后再继续发送下一帧,否则等待超时后重传该报文。该方法所需要的缓冲存储空间最小,缺点是信道效率很低。
  • 回退n帧ARQ: 发信侧不用等待收信侧的应答,持续的发送多个帧,假如发现已发送的帧中有错误发生,那么从那个发生错误的帧开始及其之后所有的帧全部再重新发送。特点:复杂度低,但是不必要的帧会再重发,所以大幅度范围内使用的话效率是不高的
  • 选择性重传ARQ: 发信侧不用等待收信侧的应答,持续的发送多个帧,假如发现已发送的帧中有错误发生,那么发信侧将只重新发送那个发生错误的帧。特点:复杂度高,但是不需要发送没必要的帧,所以效率高。
  • 混合ARQ: 在混合ARQ中,数据报文传送到接收方之后,即使出错也不会被丢弃。接收方指示发送方重传出错报文的部分或者全部信息,将再次收到的报文信息与上次收到的报文信息进行合并,以恢复报文信息。

应用:在现代的无线通信中,ARQ主要应用在无线链路层。比如,在WCDMA和cdma2000无线通信中都采用了选择性重传ARQ和混合ARQ。

滑动窗口

参考:TCP连续ARQ协议和滑动窗口协议_郭威gowill的博客-CSDN博客_arq协议

滑动窗口协议在发送方和接收方之间各自维持一个可滑动的窗口,发送方是发送窗口,接收方是接收窗口,而且这个窗口是随着时间变化可以向前滑动的。它允许发送方发送多个分组而不需等待确认,因此该协议可以加速数据的传输。TCP的滑动窗口是以字节为单位的。

发送端窗口大小 = min(拥塞窗口, 接收端窗口)

拥塞控制

图片来源: TCP的拥塞控制(详解)_程序媛_婷的博客-CSDN博客_tcp拥塞控制

TCP报文结构/三次握手/四次挥手/滑动窗口/拥塞控制_第2张图片

 

在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。

为了进行拥塞控制,TCP 发送方要维持一个 拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取为拥塞窗口和接收方的接受窗口中较小的一个。

TCP 的拥塞控制采用了四种算法,即 慢开始拥塞避免快重传快恢复。在网络层也可以使路由器采用适当的分组丢弃策略(如主动队列管理 AQM),以减少网络拥塞的发生。

  • 慢开始: 慢开始算法的思路是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么可能会引起网络阻塞,因为现在还不知道网络的符合情况。经验表明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是由小到大逐渐增大拥塞窗口数值。cwnd 初始值为 1,每经过一个传播轮次,cwnd 加倍。当前的拥塞窗口cwnd的值已经等于慢开始门限值ssthresh,之后改用拥塞避免算法。
  • 拥塞避免: 拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢增大,即每经过一个往返时间 RTT 就把发送放的 cwnd 加 1.

拥塞避免一直+1,直到达到N时,假设N个报文段在传输过程中丢失x个,接收方只收到并确认回复了N-x个报文段,一段时间后,丢失的x个报文段的重传计时器超时了,发送方判断可能出现拥塞,更改cwnd(置为1)和门限值ssthresh(发生拥塞时的一半=N/2),并重新开始慢开始算法。

个别报文会在网络中丢失,其实并未发生拥塞,TCP会错误的把cwnd置为1重新慢开始,因为降低了传输效率。所以又加入了快重传和快恢复算法来改进TCP的性能。

  • 快重传: 发送方在发送窗口内发送了6个报文,接收方回复了1、2,但是3丢失了,接着收到了4,此时接收方回复针对2号报文段的重复确认,表明我现在希望收到的是3号报文段,接着收到5、6时,继续回复2号报文段的重复确认。此时,发送方收到了累计3个连续的针对2号报文段的重复确认,立即重传3号报文段,接收方收到后,给发送方发回针对6号报文的确认,表明,序号到6为至的报文都收到了,这样就不会造成发送方对3号报文的超时重传并误以为产生拥塞,而是提早收到了重传。
  • 快恢复: 当发送方开始快重传时,即知道报文丢失时,不会以为发生拥塞重新慢开始,而是启动快恢复算法,将门限ssthresh和拥塞窗口cwnd调整为当前窗口的一半,然后开始拥塞避免算法。

UDP

  • 无连接、不可靠、效率高。
  • 面向数据报文的不可靠传输(一次一个报文),无tcp的黏包/半包问题。(tcp是面向流的可靠传输-有缓冲区)

在传送数据前不需要先建立连接,远地的主机在收到UDP报文后也不需要给出任何确认。虽然UDP不提供可靠交付,但是正是因为这样,省去和很多的开销,使得它的速度比较快,比如一些对实时性要求较高的服务,就常常使用的是UDP(比如聊天室、直播等)。对应的应用层的协议主要有 DNS,TFTP,DHCP,SNMP,NFS 等。

你可能感兴趣的:(计算机基础,tcp/ip,TCP三次握手,四次挥手,TCP滑动窗口,拥塞控制)