首页 > 技术文章 > TCP与UDP

lora404 2020-03-13 14:34 原文

TCP与UDP的区别

UDP协议是面向无连接的,也就是说不需要在正式传递数据之前连接起双方;UDP协议只是数据报文的搬运工,不保证有序且不丢失地传递到对端,具有不可靠性和高效性,适用于实时性要求高的地方;UDP支持一对多,多对多,多对一的传输方式。

TCP在建立连接和断开连接都需要先进行握手,在传输数据的过程中保证可靠性。

TCP头部

 

 

 

Sequence number这个序号保证TCP传输报文的有序性,对端可以通过序号顺序拼接报文;

Acknowledgement number表示接收端希望接收的下一个字节的编号是多少,也表示上一个序号已经收到

Window Size表示还能接收多少字节的数据,用于流量控制。

标识符

  • URG=1:该字段为一表示本数据报的数据部分包含紧急信息,是一个高优先级数据报文,此时紧急指针有效。紧急数据一定位于当前数据包数据部分的最前面,紧急指针标明了紧急数据的尾部。
  • ACK=1:该字段为一表示确认号字段有效。此外,TCP 还规定在连接建立后传送的所有报文段都必须把 ACK 置为一。
  • PSH=1:该字段为一表示接收端应该立即将数据 push 给应用层,而不是等到缓冲区满后再提交。
  • RST=1:该字段为一表示当前 TCP 连接出现严重问题,可能需要重新建立 TCP 连接,也可以用于拒绝非法的报文段和拒绝连接请求。
  • SYN=1:当SYN=1,ACK=0时,表示当前报文段是一个连接请求报文。当SYN=1,ACK=1时,表示当前报文段是一个同意建立连接的应答报文。
  • FIN=1:该字段为一表示此报文段是一个释放连接的请求报文。

建立连接的三次握手

起初,两端都为close状态。双方在开始通讯前都会创建TCB,服务器创建完TCB后便进入listen状态,等待客户端发送数据。

第一次握手

  客户端向服务端发送请求报文段,该报文段中包含自身的数据通讯初始序号,发送后,客户端便进入SYN-SENT状态。

第二次握手

  服务器接收到SYN后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入SYN-RECEIVED

第三次握手

  当客户端接收到同意连接的应答后,还要向服务端发送一个确认报文,发送完进入established状态,服务器收到这个应答也进入established状态,连接建立成功。

为什么不能两次就建立连接?

  假设:客户端发送了一个连接请求 A,但是因为网络原因造成了超时,这时 TCP 会启动超时重传的机制再次发送一个连接请求 B。此时请求顺利到达服务端,服务端应答完就建立了请求,然后接收数据后释放了连接。

  这时候连接请求 A 在两端关闭后终于抵达了服务端,那么此时服务端会认为客户端又需要建立 TCP 连接,从而应答了该请求并进入 ESTABLISHED 状态。但是客户端其实是 CLOSED 的状态,那么就会导致服务端一直等待,造成资源的浪费。

断开连接时的四次握手

第一次握手

  客户端发送完数据,向服务端发送连接释放请求。

第二次握手

  服务器接收到FIN后,告诉应用层要释放TCP连接,发送ACK包,进入close-wait状态。此时服务端不再接收客户端数据,但仍旧发送剩余数据给客户端。

第三次握手

  服务端发送完毕后会发送连接释放请求给客户端,然后服务端进入last-ack状态。(可以通过延迟机制将二三次握手合并,延迟ack的发送)

第四次握手

  客户端接收到释放请求后,向服务端发送确认应答,进入time-wait状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。

TCP延迟机制

  • 就像我们合并HTTP请求一样,TCP自身也有一种机制来合并一些ACK反馈消息,这就是延迟ACK机制。
  • 当一个数据发送时,发送方一开始并不知道数据是否发送成功,它只能等对方的ACK反馈。当然,在交互过程中一次也不止处理一个数据包,不需要确认前一个包是否已发送就可以发送后面的数据,因为接收方会负责给这些包排序,不用担心顺序问题。而延迟ACK机制就是让接收方在收到数据后不立即反馈ACK消息,而是等到一小段时间,如果之后还有收到其他包就把这些ACK消息一起放入一个包中反馈给客户端。
  • 延迟有一个时间限制,通常不会超过200ms。

TCP流量控制

利用滑动窗口实现流量控制

  流量控制就是让发送方的发送速率不要太快,使接收方来得及接收。根本目的是防止分组丢失,构成TCP可靠性的一方面。

  滑动窗口协议(连续ARQ协议),主要方式是接收方返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。

由流量控制引发的死锁

  当发送者接收到一个窗口为0的应答,便会停止发送,等待接收者的下一个应答。如果这个窗口不为0的应答在传输过程中丢失,发送者会一直等待,而接受方也在等待接收新数据,从而产生死锁。

  为了避免死锁,TCP使用了连续计时器。每当发送方接收到一个零窗口应答后就启动。时间一到便主动询问接收者窗口大小。若接收者仍返回0窗口,则重置该计时器继续等待;若不为0,则表示应答报文丢失,此时重置发送窗口后发送。

 

TCP拥塞控制

拥塞控制是作用于网络的,防止过多的数据拥塞网络,避免出现网络负载过大的情况。

  拥塞处理包括了四个算法,分别为:慢开始,拥塞避免,快速重传,快速恢复。

  我们开始假定:1、数据是单方向传递,另一个窗口只发送确认;2、接收方的缓存足够大,因此发送方的大小的大小由网络的拥塞程度来决定

慢开始算法

慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。

想必大家都下载过资源,每当我们开始下载的时候都会发现下载速度是慢慢提升的,而不是一蹴而就直接拉满带宽。

为了防止cwnd增长过大引起网络拥塞,还需设置一个慢开始门限ssthresh状态变量。ssthresh的用法如下:当cwnd<ssthresh时,使用慢开始算法。
当cwnd>ssthresh时,改用拥塞避免算法。
当cwnd=ssthresh时,慢开始与拥塞避免算法任意

拥塞避免算法

拥塞避免算法相比简单点,每过一个往返时间 RTT就把发送方的拥塞窗口加一,而不是加倍,这样能够避免指数级增长导致网络拥塞,慢慢将大小调整到最佳值。

快速重传算法

快速重传一般和快恢复一起出现。一旦接收端收到的报文出现失序的情况,接收端只会回复最后一个顺序正确的报文序号。如果发送端收到三个重复的 ACK,立刻重传对方尚未收到的报文。无需等待重传定时器超时。

快恢复算法

 

当发送方连续接受到三个重复确认的时候,就执行“乘法减小”算法,将ssthresh减半,此时不执行慢开始,而是拥塞避免,使拥塞窗口缓慢增大。

 

 

注意:在采用快恢复算法时,慢开始算法只是在TCP连接建立时和网络出现超时时才使用

推荐阅读