TCP和UDP

TCP协议保证数据传输可靠性的方式主要有:

  • 校验和
  • 序列号
  • 确认应答
  • 超时重传
  • 连接管理
  • 流量控制
  • 拥塞控制

TCP报头
TCP和UDP_第1张图片

  1. 源端口和目的端口:各占2个字节

  2. 序号:占4个字节,也称顺序号

  3. 确认序号:占4个字节,简称ACK,在握手阶段,确认序号将发送方的序号加1作为回答

  4. 首部长度(数据偏移):4位,首部含有长度不确定的选择字段,因此数据偏移字段必须有.TCP的首部长度最大位60字节

  5. 6位标志字段:
    1)确认ACK:仅当ACK=1的确认号字段才有效,当ACK=0时,确认号无效,TCP规定,在连接建立后所有的传送的报文段都必 须把ACK置1

    2)复位RST置1时重新连接,如果接收到RST位时候,通常发送了某些错误.

    3)同步SYN置1时用来发起一个连接

    4)终止FIN置1时表示发送端完成发送任务,用来释放连接

    5)紧急指针URG,告诉接收TCP模块紧要指针域指着紧要数据

    6)推送PSH置1请求的数据段在接收方得到后可直接发到应用程序,而不必等到缓冲区满时才传送.

  6. 检验和:2个字节,检验范围包括首部和数据两部分,和UDP用户数据报一样,在计算校验和时,要在TCP报文段加上12字节的伪首部

  7. 紧急指针:2字节,紧急指针仅在URG=1时才有意义,指出本报文段中的紧急数据的字节数.

  8. 选项:长度可变,最长可达40字节.当没有选项的时候,TCP的首部长度为20字节.


UDP报头
TCP和UDP_第2张图片
UDP首部(8字节)

  1. 源端口:2字节,一个大于1023的16位数字,基于UDP应用程序的用户进程随机选择.
  2. 目的端口:2字节
  3. 长度字段:2字节,表示包括首部在内的UDP报文段长度.
  4. 校验和:2字节,是指整个UDP报文头和UDP数据的校验和(包括伪报文头)

TCP和UDP的比较
TCP和UDP_第3张图片

  • TCP提供可靠的服务,TCP连接传送的数据,无差错,不丢失,不重复,且按顺序到达,UDP尽量交付,即不保证可靠交付
  • TCP面向字节流,UDP面向报文
  • TCP只能1对1,UDP支持1对1,1对多,多对1
  • TCP首部开销20字节,UDP8字节,UDP首部开销小
  • UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速度降低(一把用作实时应用,IP电话,实时视频等)

UDP如何实现可靠性传输
传输层无法保证数据的可靠性,只能通过应用层来实现,实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到应用层
实现 确认机制,重传机制
实现流量控制:滑动窗口
实现拥塞控制:慢开始和拥塞避免,块重传和块恢复


TCP连接过程的三次握手
TCP和UDP_第4张图片
序列号seq:占4个字节,用来标记数据段的顺序
确认号ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号
同步SYN:连接建立时用于同步序号
终止FIN:用来释放一个连接
确认ACK:占1位,仅当ACK=1时,确认号字段才有效

第一次握手
客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入 SYN-SENT 状态。
第二次握手
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入 SYN-RECEIVED 状态。
第三次握手
当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功。
这里可能大家会有个疑惑:为什么 TCP 建立连接需要三次握手,而不是两次?这是因为这是为了防止出现失效的连接请求报文段被服务端接收的情况,从而产生错误。

四次挥手
TCP和UDP_第5张图片
(1)客户段想要释放连接,向服务端发送tcp报文(FIN=1,seq=u),进入半关闭状态(FIN-WAIT-1),不会发送数据(非确认报文),但还能接受服务端的数据.
(2)服务端收到客户端的tcp报文,确认了客户端想到释放连接,进入半关闭状态(CLOSED-WAIT),并向客户端发送一段tcp报文(Seq=v,ack=u+1),然后服务端准备释放服务器到客户端的连接
客户端收到服务端的报文后,确认了服务器收到客户端发送的释放连接的请求,结束FIN-WAIT-1阶段,进入FIN-WAIT-2阶段
(3)服务端经过CLOSED-WAIT阶段,做好了释放服务端和客户端之间连接的准备,再向客户端发送一段TCP报文(seq=w,ack=u+1),然后服务端进入LAST-ACK阶段,停止向客户端发送数据,但仍然能接收数据
(4)客户端接收了TCP报文,确认了服务端已经做好了释放连接的准备,结束FIN-WAIT-2阶段,进入TIME-WAIT阶段,并向服务端发送一段报文(seq=u+1,ack=w+1),随后客户端再TIME-WAIT阶段等待2MSL后进入CLOSE阶段,服务器也收到客户端的报文后,结束LAST-ACK阶段,进入CLOSED阶段

1.为什么握手是三次,挥手是四次?
建立连接时,ACK和SYN可以放再同一报文中发送,关闭连接的时候,还可能需要发送一些数据,等数据都发送完了,再发送FIN报文表示做好了准备关闭连接
2.为什么TIME_WAIT后要等待2MSL后才进入关闭状态?
无法保证最后发送的ACK报文一定会被对方收到,服务端在1MSL内没有收到客户端发送的ACK确认报文,就会再次发送FIN报文,然后客户端重发,再进行2MSL的等待
3.为什么不能2次握手?
中间传输如果丢失,可能发送死锁,即服务端不知道要建立连接
4.如果已经建立了连接,但是客户端突然出现故障了怎么办
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去.服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接.


TCP的拥塞控制
在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络性能就会变坏,这种清空就叫做网络拥塞.
在计算机网络中数位链路容量(带宽),交互结点中的缓存和处理机,都是网络资源
若出现拥塞而不进行控制,整个网络的吞吐量将随输入负荷的增大而下降
TCP和UDP_第6张图片
TCP的四种拥塞控制算法:
1.慢开始
2.拥塞控制
3.快重传
4.快恢复
假定:
1.数据是单方向传送,而另一个方向只传送确认
2.接收方总是有足够大的缓存空间,因而发送发发送窗口的大小由网络的拥塞程度来决定
3.以TCP报文段的个数为讨论问题的单位,而不是以字节为单位
TCP和UDP_第7张图片
示例如下:
传输轮次:发送方给接收方发送数据报文段后,接收方给发送方发回相应的确认报文段,一个传输轮次所经历的时间就是往返时间RTT(RTT并非是恒定的数值),使用传输轮次是为了强调,把拥塞窗口cwnd所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个报文段的确认,拥塞窗口cwnd会随着网络拥塞程度以及所使用的拥塞控制算法动态变化。

在tcp双方建立逻辑链接关系时, 拥塞窗口cwnd的值被设置为1,还需设置慢开始门限ssthresh,在执行慢开始算法时,发送方每收到一个对新报文段的确认时,就把拥塞窗口cwnd的值加一,然后开始下一轮的传输,当拥塞窗口cwnd增长到慢开始门限值时,就使用拥塞避免算法。

慢开始:
假设当前发送方拥塞窗口cwnd的值为1,而发送窗口swnd等于拥塞窗口cwnd,因此发送方当前只能发送一个数据报文段(拥塞窗口cwnd的值是几,就能发送几个数据报文段),接收方收到该数据报文段后,给发送方回复一个确认报文段,发送方收到该确认报文后,将拥塞窗口的值变为2,

发送方此时可以连续发送两个数据报文段,接收方收到该数据报文段后,给发送方一次发回2个确认报文段,发送方收到这两个确认报文后,将拥塞窗口的值加2变为4,发送方此时可连续发送4个报文段,接收方收到4个报文段后,给发送方依次回复4个确认报文,发送方收到确认报文后,将拥塞窗口加4,置为8,发送方此时可以连续发送8个数据报文段,接收方收到该8个数据报文段后,给发送方一次发回8个确认报文段,发送方收到这8个确认报文后,将拥塞窗口的值加8变为16

当前的拥塞窗口cwnd的值已经等于慢开始门限值,之后改用拥塞避免算法。
拥塞避免:
也就是每个传输轮次,拥塞窗口cwnd只能线性加一,而不是像慢开始算法时,每个传输轮次,拥塞窗口cwnd按指数增长。同理,16+1……直至到达24,假设24个报文段在传输过程中丢失4个,接收方只收到20个报文段,给发送方依次回复20个确认报文段,一段时间后,丢失的4个报文段的重传计时器超时了,发送发判断可能出现拥塞,更改cwnd和ssthresh.并重新开始慢开始算法,如图所示:
TCP和UDP_第8张图片
TCP和UDP_第9张图片
快速重传:
发送方发送1号数据报文段,接收方收到1号报文段后给发送方发回对1号报文段的确认,在1号报文段到达发送方之前,发送方还可以将发送窗口内的2号数据报文段发送出去,接收方收到2号报文段后给发送方发回对2号报文段的确认,在2号报文段到达发送方之前,发送方还可以将发送窗口内的3号数据报文段发送出去,

假设该报文丢失,发送方便不会发送针对该报文的确认报文给发送方,发送方还可以将发送窗口内的4号数据报文段发送出去,接收方收到后,发现这不是按序到达的报文段,因此给发送方发送针对2号报文段的重复确认,表明我现在希望收到的是3号报文段,但是我没有收到3号报文段,而收到了未按序到达的报文段,发送方还可以将发送窗口中的5号报文段发送出去,接收方收到后,发现这不是按序到达的报文段,因此给发送方发送针对2号报文段的重复确认,表明我现在希望收到的是3号报文段,但是我没有收到3号报文段,而收到了未按序到达的报文段,,发送方还可以将发送窗口内的最后一个数据段即6号数据报文段发送出去,接收方收到后,发现这不是按序到达的报文段,因此给发送方发送针对2号报文段的重复确认,表明我现在希望收到的是3号报文段,但是我没有收到3号报文段,而收到了未按序到达的报文段,

此时,发送方收到了累计3个连续的针对2号报文段的重复确认,立即重传3号报文段,接收方收到后,给发送方发回针对6号报文的确认,表明,序号到6为至的报文都收到了,这样就不会造成发送方对3号报文的超时重传,而是提早收到了重传。
TCP和UDP_第10张图片
TCP和UDP_第11张图片
快速恢复算法:
TCP Reno算法定义在RFC5681。快速重传和快速恢复算法一般同时使用。快速恢复算法认为,你还有3个Duplicated Acks说明网络也不那么糟糕,所以没有必要像RTO超时那么强烈,并不需要重新回到慢启动进行,这样可能降低效率。所以协议栈会做如下工作:

  • 拥塞窗口减半cwnd=cwnd/2
  • 慢开始门限ssthresh=cwnd(减半后的值)

然后启动快速恢复算法:

  • 设置cwnd = ssthresh+ack个数(一般情况下会是3个Dup Acks),然后重传指定的数据包;
  • 如果再次收到Dup Acks,则cwnd=cwnd+1, 并且在条件允许的情况下发送下一个报文段(非重传报文段)
  • 如果收到新的ACK, 则快速恢复算法结束,设置cwnd = ssthresh, 进入拥塞避免阶段
    TCP和UDP_第12张图片
    TCP New Reno
  • 这个算法是Reno算法的改进,没有使用SACK机制
    当sender这边收到了3个Duplicated Acks,进入Fast Retransimit模式,开始重传重复Acks指示的那个包。如果只有这一个包丢了,那么,重传这个包后回来的Ack会把整个已经被sender传输出去的数据ack回来。如果没有的话,说明有多个包丢了。我们叫这个ACK为Partial ACK。
  • 一旦Sender这边发现了Partial ACK出现,那么sender就可以推理出来有多个包被丢了,于是乎继续重传sliding window里未被ack的第一个包。直到再也收不到了Partial Ack,才真正结束Fast Recovery这个过程

滑动窗口
滑动窗口实现了TCP流控制。首先明确滑动窗口的范畴:TCP是双工的协议,会话的双方都可以同时接收和发送数据。TCP会话的双方都各自维护一个发送窗口和一个接收窗口。各自的接收窗口大小取决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。各自的发送窗口则要求取决于对端通告的接收窗口,要求相同。

滑动窗口解决的是流量控制的的问题,就是如果接收端和发送端对数据包的处理速度不同,如何让双方达成一致。接收端的缓存传输数据给应用层,但这个过程不一定是即时的,如果发送速度太快,会出现接收端数据overflow,流量控制解决的是这个问题
滑动机制

  1. 发送窗口只有收到发送窗口内字节的ACK确认,才会移动发送窗口的左边界。
  2. 接收窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保对端会对这些数据重传。
  3. 遵循快速重传、累计确认、选择确认等规则。
  4. 发送方发的window size = 8192;就是接收端最多发送8192字节,这个8192一般就是发送方接收缓存的大小
    具体演示:https://blog.csdn.net/yao5hed/article/details/81046945

参考:
https://blog.csdn.net/qq_41431406/article/details/97926927
https://blog.csdn.net/bailu666666/article/details/79725804

你可能感兴趣的:(TCP和UDP)