TCP/UDP 区别详解

684 阅读18分钟

TCP/UDP 区别详解

引言

TCP、UDP是属于TCP/IP协议簇中的一个,之所以命名为TCP/IP协议是因为在TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。TCP/IP协议严格来说是一个四层的体系结构包括:应用层、传输层、网络层和数据链路层,TCP、UDP协议正是位于传输层的协议。

  • 应用层:用来接收来自传输层的数据或者按不同应用要求与方式将数据传输至传输层,主要协议有Telnet、FTP、SMTP等
  • 传输层:提供了一种端到端的连接,可以实现数据传输与数据共享
  • 网络层:主要负责网络中数据包的传送等,主要协议有ICMP、IP、IGMP
  • 数据链路层(网络接口层):主要功能是提供链路管理错误检测、对不同通信媒介有关信息细节问题进行有效处理等,主要协议有ARP、RARP。

UDP

   UDP(User Datagram Protocol) 不提供复杂的控制机制,利用ip提供面向无连接的通信服务。并且它是将应用程序发来的数据在收到的那一刻,立即按照原样发送到网络上的一种机制。

数据格式

每个UDP报文分为UDP报头和UDP数据区两部分。报头由4个16位长(2 字节)字段组成,分别说明该报文的源端口、目的端口、报文长度和校验值。 源端口号(Source Port) 这个字段占据 UDP 报文头的前 16 位,通常包含发送数据报的应用程序所使用的 UDP 端口。接收端的应用程序利用这个字段的值作为发送响应的目的地址。这个字段是可选项,有时不会设置源端口号。没有源端口号就默认为 0 ,通常用于不需要返回消息的通信中。

目标端口号(Destination Port) 表示接收端端口,字段长为 16 位 长度(Length): 该字段占据 16 位,表示 UDP 数据报长度,包含 UDP 报文头和 UDP 数据长度。因为 UDP 报文头长度是 8 个字节,所以这个值最小为 8,最大长度为 65535 字节。

校验和(Checksum):UDP 使用校验和来保证数据安全性,UDP 的校验和也提供了差错检测功能,差错检测用于校验报文段从源到目标主机的过程中,数据的完整性是否发生了改变。

UDP特点

    UDP无法在网络拥堵的情况下,进行流量控制等避免网络堵塞的行为。此外在传输途中即使出现丢包,UDP也不负责重发。甚至当包的到达顺序乱掉时也没有纠正的功能。

  • 需要资源少 每个 TCP 报文段都有 20 字节的首部开销,而 UDP 仅仅只有 8 字节的开销。
  • 不面向连接 可以使得可以承载广播或者多播的协议。DHCP 就是一种广播的形式,就是基于 UDP 协议的。
  • 处理速度快 时延低,可以容忍少数丢包,但是要求即便网络拥塞,也毫不退缩,一往无前,UDP简单、处理速度快。TCP 有拥塞控制的功能,它会在发送前判断互联网的拥堵情况,如果互联网极度阻塞,那么就会抑制TCP的发送方。

TCP

数据格式

  • 源端口号目的端口号,计算机通过端口号识别访问哪个服务,比如http服务或ftp服务,发送方端口号是进行随机端口,目标端口号决定了是哪个程序来接受
  • TCP用32 位的序列号字段(sequence number field) 对数据包进行标记,以便在到达目的后重新重装,假设当前的序列号为s,发送数据长度为l,则下次发送数据的序列号为s+l。在建立连接时通常由计算机生成一个随机数作为序列号的初始值。
  • 确认号字段(acknowledgment number field) 表示期望收到的下一个字节的序号,TCP通过肯定的确认应答ACK 实现可靠的数据传输。当发送端将数据发出之后会等待对端的确认应答。如果有确认应答,说明数据已经成功到达对端。反之,则数据丢失的可能性很大。
  • 数据偏移(首部字段长度字段(header length field)),表示以 32 比特的字为单位的 TCP 首部长度。TCP 首部的长度是可变的,但是通常情况下,选项字段为空,所以 TCP 首部字段的长度是 20 字节。
  • 接受窗口字段(receive window field) ,这个字段用于流量控制。它用于指示接收方能够/愿意接受的字节数量
  • 可变的选项字段(options field),这个字段用于发送方和接收方协商最大报文长度,也就是 MSS 时使用
  • 标志字段(flag field)ACK 标志用于指示确认字段中的值是有效的,这个报文段包括一个对已被成功接收报文段的确认;RSTSYNFIN 标志用于连接的建立和关闭;CWRECE 用于拥塞控制;PSH 标志用于表示立刻将数据交给上层处理;URG 标志用来表示数据中存在需要被上层处理的 紧急 数据。紧急数据最后一个字节由 16 比特的紧急数据指针字段(urgeent data pointer field) 指出。一般情况下,PSHURG 并没有使用。

通过序列号与确认应答提高可靠性

    在TCP中,当发送端的数据到达接受主机时,接受端主机会返回一个已收到消息的通知。这个消息叫做确认应答。     通常,两个人对话时,在谈话的停顿处可以点头或询问以确认谈话内容。如果对方迟迟没有任何反馈,说话的一方可以重复在发送一遍以保证对方确实可以听到。因此,对方是否理解了此次对话内容,对方是否完全听到了对话的内容,都要靠对方的反应来判断。网络中的'确认应答'就是类型这样的一个概念。当对方听懂对话的内容时会说:“嗯”,这就相当于返回了一个确认应答 ACK。而当对方没有理解对话内容或没有听清时,会问一句,“啥?”这就好比一个否定的确认应答NACK    TCP 通过肯定的确认应答(ACK) 来实现可靠的数据传输,当主机 A将数据发出之后会等待主机 B 的响应。如果有确认应答(ACK),说明数据已经成功到达对端。反之,则数据很可能会丢失。

数据丢包的情况

    如下图所示,如果在一定时间内主机A没有等到确认应答,则认为主机B发送的报文段已经丢失,并进行重发。 当数据A由主机A发出后如果因网络堵塞等原因丢失的话,该数据将无法到达主机B。此时,如果主机A在一个特定时间间隔都未收到主机B发来的确认应答,将会对称数据进行重发

确认应答丢失的情况

   未收到确认应答并不意味着数据一定丢失。也有可能是数据对方已将收到,只是返回的确认应答在途中丢失。这种情况也会导致发送端因没有收到确认应答,而认为数据没有到达目的地,从而进行重新发送 由主机B返回的确认应答,因网络堵塞等原因在传送的途中丢失,没有到达主A。主机A会等待一段时间,若在特定的时间间隔内始终未能收到这个确认应答,主机A会对此数据进行重发。此时,主机B将第二次发送已接收此数据的确认应答。由于主机B其实已经收到过0-999的数据,当再有相同的数据送达时它会放弃。

序列号与确认应答是如何可靠传输的

如果一段时间内源主机没能收到目的主机返回的确认应答,此时源主机只要按照机制重发数据即可。但是对于目标主机来说,这啵操作简直是多余的。它会反复收到相同的数据,而为了对上层应用提供可靠的传输,必须得放弃重复的数据包。

通过序列号就可以处理这类问题。序列号是按顺序给发送数据的每一个字节(8位字节)都标上号码的编号。接收端查询接受数据TCP首部中的序列号和数据的长度,将自己下一次应该接收的序号作为确认应答返送回去。就这样,TCP通过序列号与确认应答号实现可靠传输。

重发超时如何确定

超时重发:是指在重发数据之前,等待确认应答到来的那个特定的时间间隔。如果超过了这个时间仍未收到确认应答,发送端将进行数据重发。

RTT(Round-Trip Time): 往返时延,一个重要的性能指标,表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。

TCP为了在无论何种网络环境下都要提供高性能通信,并且无论网络堵塞情况发生何种变化,都必须保持这一特性,为此,它在每次发包是时都会计RTT及其偏差(RTT时间波动的值、方差)。将这个往返的时间和偏差想加,重发超时的时间就是比这个总和要大一些的值。

拥塞预防及控制

   在某段时间,若对网络中的某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏,这种情况叫做拥塞。这个原因可能是往返时间超过了所有主机的最大中断间隔,于是相应的主机会在网络中制造越来越多的数据报副本,使得整个网络陷入瘫痪网络拥塞,简单的提高节点处理机的速度或者扩大结点缓存的存储空间并不能解决拥塞问题。例如,当某个结点缓存容量扩展到非常大,于是凡到达该结点的分组均可在结点的缓存队列中排队,不受任何限制。由于输出链路的容量和处理机的速度并未提高,因此在这队列中的绝大多数的分组在排队等待时间会大大增加,结果上层软件只好把他们进行重传。因此,问题的是指往往是整个系统的各个部分不匹配,只有各个部分平衡了,问题才会得到解决。

为了解决上诉问题,TCP 加入了很多机制,以便控制双向发送数据的速度,比如流 量控制、拥塞控制和拥塞预防机制。

利用窗口提高速度

TCP是以一个段为单位发送数据,每发一个段进行一次确认应答的处理,对每一个包都要等待确认应答,这样做的缺点就是包的往返时间越长,网络的吞吐量越差,性能越差。

滑动窗口方式并行处理

   为了解决这个问题,TCP引入了窗口的概念,即使在往返时间较长的情况下,它也能控制网络性能的下降。如图,确认应答不再是以每个分段,而是以更大的单位进行确认时,转发时间将会被大幅度缩短。也就是说,发送端主机,在发送了一个段以后没必要一直等待确认应答,而是继续发送。    我们之前每次请求发送都是以报文段的形式进行的,引入窗口后,每次请求都可以发送多个报文段,也就是说一个窗口可以发送多个报文段。窗口大小就是指无需等待确认应答就可以继续发送报文段的最大值。

   在这个窗口机制中,大量使用了缓冲区,通过对多个段同时进行确认应答的功能。

   如下图参考图解TCP/IP,发送报文段中高亮(白色部分)即是我们提到的窗口,在窗口内,即是没有收到确认应答也可以把请求发送出去。不过,在整个窗口的确认应答没有到达之前,如果部分报文段丢失,那么发送端(主机A) 将仍会重传。为此,发送端(主机A) 需要设置缓存来保留这些需要重传的报文段,直到收到他们的确认应答。

   在滑动窗口以外的部分包括尚未发送的数据以及已经确认对端已收到的数据。当数据发出后若如期收到确认应答可以不用再进行重发,此时数据就可以从缓存区清除。

   收到确认消息应答的情况下,将窗口滑动到确认应答的序号位置。这样可以顺序地将多个段同时发送提高通信性能,这种机制也被称为滑动窗口控制

流量控制

   流量控制是一种预防发送端过多向接收端发送数据的机制。否则,接收端可能因为忙碌、负载重或缓冲区既定而无法处理。为实现流量控制,TCP连接的每一方都要通告自己的接收窗口,其中包含能够保存数据的缓冲区空间大小信息。具体的操作是,接收端主机向发送端主机通知自己可以接收数据的大小,于是发送端会发送不超过这个限度的数据。该大小限度就被称作窗口大小。

   TCP首部中,专门有一字段用来通知窗口大小。接收主机将自己可以接收的缓冲区大小放入这个字段中通知给发送端。这个字段的值越大,说明网络的吞吐量越高。但是一旦接收端的缓冲区面临溢出时,窗口大小的值会随之被设置为一个更小的值通知给发送端,从而控制数据发送量。

那么这个上面这个字段是如何控制的呢?

发送端主机会定期发送一个窗口探测包,这个包用于探测接收端主机是否还能够接受数据,当接收端的缓冲区一旦面临数据溢出的风险时,窗口大小的值也随之被设置为一个更小的值通知发送端,从而控制数据发送量。

如图,当接收端收到从3001号开始的数据段后其缓冲区即满,不得不暂时停止接收数据。之后,在收到发送窗口更新通知后通信才得以继续进行。如果这个窗口的更新通知 在途中发生了丢失,可能会导致无法通信。为避免这类问题的发生,发送端会时不时的发送一个叫窗口探测的数据段,此数据段仅含一个字节以获取最新的窗口大小信息。

拥塞控制

   有了 TCP 的窗口控制后,使计算机网络中两个主机之间不再是以单个数据段的形式发送了,而是能够连续发送大量的数据包。然而,大量数据包同时也伴随着其他问题,比如网络负载、网络拥堵等问题。TCP 为了防止这类问题的出现,使用了拥塞控制机制,拥塞控制机制会在面临网络拥塞时遏制发送方的数据发送。也就是说,发送端和接收端在连接建立之初,谁也不知道可用带宽是多少,因此需要一个估算机制,然后还要根据网络中不断变化的条件 而动态改变速度。

   TCP为了防止该问题的出现,在通信一开始时就会通过一个叫做慢启动的算法得出的数值,对数据量进行控制。

慢启动

   要理解慢启动,最好看一个例子。同样,假设纽约有一个客户端,尝试从位于伦敦的服务器上取得一个文件。首先,三次握手,而且在此期间双方各自通过 ACK 分组通告自己的接收窗口(rwnd)大小。在发送完最后一次 ACK 分组后, 就可以交换应用数据了。此时,根据交换数据来估算客户端与服务器之间的可用带宽是唯一的方法,而且这也是慢启动算法的设计思路。首先,服务器通过 TCP 连接初始化一个新的拥塞窗口 (cwnd)变量,将其值设置为一个系统设定的保守值(在 Linux 中就是initcwnd)。

拥塞窗口大小(cwnd)

   拥塞窗口大小(cwnd) 是指发送端对从客户端接收确认(ACK)之前可以发送数据量的限制。发送端不会通告cwnd变量,即发送端和接收端不会交换这个值。他们之间的规则是客户端与服务器之间最大可以传输(未经 ACK 确认的)数据量取 rwnd 和 cwnd 变量中的最小值。

网络状况随时都在变化,那服务器和客户端怎么确定拥塞窗口大小的最优值呢?    那如果能通过算法来确定每个连接的窗口大小,而不用手工调整就最好了。解决方案就是慢启动,即在分组被确认后增大窗口大小,慢慢地启动!最初,cwnd 的值只有 1个TCP段。而到了2013年4月,RFC6928再次将其提高到10个TCP段。新TCP连接传输的最大数据量取rwnd和cwnd中的最小值,而服务器实际上可以向客户端发送4个TCP段,然后就必须停下来等待确认。此后,每收到一个ACK,慢启动算法就会告诉服务器可以将它的cwnd窗口增加1个TCP段。每次收到ACK后,都可以多发送两个新的分组。TCP连接的这个阶段通常被称为“指数增长”阶段,因为客户端和服务器都在向两者之间网络路径的有效带宽迅速靠拢。    当TCP通信开始以后,网络的吞吐量会渐渐上升,但是随着网路拥堵的发生吞吐量也会急速下降。于是会再次进入吞吐量慢慢上升的过程。因此所谓的TCP的吞吐量的特点就好像在逐步占领网络宽带。

提高网络利用率

Nagle算法

   TCP中为了提高网络的利用率,使用了一个叫做Nagle的算法,也就是说发送端即使还有用该发送的数据,但是如果这部分数据很少的话,则进行延迟发送的一种机制。具体来说,就是仅在下列任意一种条件下才能发送数据。如果两个条件都不满足,那么暂时等待一段时间以后再进行数据发送。

  • 已发送的数据都已经收到确认应答时
  • 可以发送最大段长度(MSS)的数据时
延迟确认应答

    接收数据的主机如果因为刚接收到数据缓存区已满,每次都立刻回复确认应答的话,可能会返回一个较小的窗口。当某个接收端收到这个小窗口的通知以后,会以它为上限发送数据,从而又降低了网络的利用率。为此引入一个方法---延迟确认(delayed ack) 稍稍延迟,然后合并 ACK,最后才回复给发送端。TCP 要求这个延迟的时延必须小于500ms,很多操作系统都设置为200ms左右。