【计算机网络】传输层的UDP与TCP协议解析

目录

1 TCP/IP模型

2 传输层协议概述

3 进程标识符——端口

4 UDP协议

4.1 UDP概述

4.2 UDP首部格式

5 TPC协议

5.1 TCP概述

5.2 TCP首部格式

5.3 TCP连接的建立和释放

5.3.1 建立连接

5.3.2 释放连接

5.4 TCP可靠传输的实现

TCP可靠传输的工作原理

停止等待协议

连续ARQ协议

TCP滑动窗口和缓存

以字节为单位的滑动窗口

发送接收缓存

缓存和窗口的关系

TCP流量控制

滑动窗口实现流量控制

TCP里的策略提升传输效率

TCP拥塞控制

拥塞判断

拥塞控制算法

拥塞控制实现过程


1 TCP/IP模型

2 传输层协议概述

从网际层来看,通信的主体是两台主机,ip数据报的首部已经包含了源主机ip地址和目的主机ip地址(没有端口号)。在网络传输时,路由器会依据首部的ip地址将分组从当前网络转发到目的主机所在的网络,最终将ip数据报发送给目的主机。那现在既然已经能把数据传送到目的主机了,为什么还要传输层?

这里我们就要清楚数据交换的实质。表面上看数据是从一个主机发送到另一个主机,但实际上真正进行数据交互的是主机中的具体进程。网络层中的ip协议虽然能把分组送到目的主机,但这个分组数据还停留在主机的网络层而没有交付到主机中的应用进程,也就是说端到端的通信应该是应用进程之间的通信。所以我们可以得出一些结论:

  • 网络层提供主机之间的逻辑通信,传输层为应用进程之间提供端到端的逻辑通信。
  • 传输层会提供网络层没有的很多功能,如:流量控制,可靠传输,拥塞控制等。

上面提到的逻辑通信并不是说两个传输层之间的通信是水平方向的数据传输(见下图),而是经历了一系列的拆包,加包才最终将分组从主机A的应用层发送到主机B的对应进程。中间两个只有三层协议栈的是路由器,因为路由器只需要将分组整个转发到目的主机即可,所以它的协议栈只有最底下三层。

根据应用程序的不同需求,运输层主要有两种协议,即面向连接的TCP和无连接的UDP。

3 进程标识符——端口

操作系统在创建一个进程时,除了要给该进程分配运行所必须的环境和资源之外,还必须分配一个未被占用的端口,通过该端口可以实现进程之间的通信。运输层用一个16位的端口号来标识一个端口,其允许有65535个不同的端口号,可以分为两类。

  • 服务器端使用的端口号:0~1023。如:FTP-21,TELNET-23,HTTP-80等。
  • 客户端使用的端口号:1024~65535。又叫短暂端口号。通信结束后,刚才使用过的客户端口号就不复存在,这个端口号就可以供其他客户进程使用。

端口拼接到ip地址即构成了套接字,即:套接字socket = (IP地址 : 端口号)。

4 UDP协议

4.1 UDP概述

  1. UDP是无连接的。即发送数据之前不需要建立连接,最后也不需要释放连接,这样的连接不保证可靠传输
  2. UDP是面向报文的。对于应用层交下来的报文,在添加首部后就直接下交到ip层(TCP一次仅交付报文的若干字节,因为要考虑到接受端缓存大小,网络拥塞等问题);对于IP曾上交上来的报文,去除首部后就原封不动地交付上层的应用进程。
  3. UDP没有拥塞控制。TCP在发生拥塞时会控制分组发送的速率以降低丢包率,而UDP因为不保证可靠传输,所以无需进行拥塞控制,提高了分组发送的效率,在某些场景下更能满足现实需求,如:语音或视频通话。
  4. UDP支持一对一,一对多,多对一和多对多的交互通信。而TCP只能是一对一,因为连接只能在两个主机间建立。
  5. UDP的首部开销比TCP小,UDP首部为8个字节,TCP为20个字节。

4.2 UDP首部格式

UDP首部总共有8个字节,由4个字段组成,每个字段占2个字节,各字段的意义如下:

  1. 源端口。源主机产生该分组数据的进程所绑定的端口号。
  2. 目的端口。接受该分组的目的主机进程所绑定的端口号。
  3. 长度。整个UDP数据报(分组)的长度,最小值为8(仅有首部,UDP数据报由首部和数据部分组成)
  4. 校验和。检测UDP数据报在传输过程中是否有错,检测发生在目的主机的传输层。检测内容仅包括首部。

4.3 UDP如何实现可靠传输

  • 分析:UDP实现可靠传输只能在应用层去实现,发送端程序(A)和接收端程序(B)约定可靠传输的协议,规定发送和接受的规则。
  • 基础功能:依照TCP,在应用程序中应该实现:发送确认、分组重复或出错丢弃、超时重传、流量控制、拥塞控制。

底层数据结构:

  • 确认字段:为每种确认字段设置一个对应的变量,如seq、ack、syn、rwnd、cwnd等。
  • 缓存和滑动窗口:在A和B中设置发送和接受的缓存,使用数组来实现,每个数组设置两个指针,指针之间的区域表示滑动窗口。每次连接建立后就创建数组(缓存),连接断开就释放。
  • 传输报文段:使用一个Java Bean来表示分组,包括头部(确认字段)和数据段,Java bean可序列化,在网络上传输。

功能实现:

  • 出错丢弃:使用md5校验数据是否在传输中出错。

md5校验原理:如客户往我们数据中心同步一个文件,该文件使用MD5校验,那么客户在发送文件的同时会再发一个存有校验码的文件,我们拿到该文件后做MD5运算,得到的计算结果与客户发送的校验码相比较,如果一致则认为客户发送的文件没有出错,否则认为文件出错需要重新发送。

  • 超时重传:为每一次分组发送设置计时器,到期了就重新发送分组。
  • 流量控制:接收方通过判断缓存数组的剩余容量大小,设置确认中的窗口值。
  • 拥塞控制:通过拥塞控制方法。

5 TPC协议

5.1 TCP概述

  1. TCP是面向连接的。发送数据前必须建立连接,传送完毕后必须释放连接。
  2. TCP是面向字节流的。TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字4e节流,然后将这些字节流分批发送给目的主机,每次发送的流块大小不等,详情见“TCP可靠传输的实现”。
  3. TCP提供可靠交付。通过TCP连接传送的数据,无差错,不丢失,不重复,且按顺序到达。
  4. TCP只支持一对一通信,因为连接只能在两个主机间建立。

5.2 TCP首部格式

是理解TCP连接的建立释放、可靠传输、流量控制的关键,务必弄清楚下面几个首部字段的含义(可对照TCP连接释放章节来理解)。下图显示TCP首部字段有很多,这里我只挑选了讲解内容用得到的字段,而且精简了内容,希望能让你看得懂。

  1. 源端口和目的端口。各占2个字节,和UDP类似。
  2. 序号(seq)。指本报文段所发送的数据的第一个字节的序号。占32位,4个字节,序号范围是[0,2^32-1],序号增加到2^32-1后,下一个序号又回到0,以此类推。TCP是面向字节流的,字节流中每一个字节都按顺序编号。整个要传送的字节流的起始序号必须在建立连接时设置,后面再发送的字节流的序号由接收(发送)端通过“确认号”指定。(客户端和服务端发送的字节流是独立的,所以seq也是独立的)。
  3. 确认号(ack)。期望收到对方下一个报文段的第一个数据字节的序号,与序号一样占4字节。如接收端收到了发送端序号为200,数据长度为100的报文段,然后在返回报文段时设置确认号为301,那么下次发送端发送的字节序号就是从301开始,表示到序号300为止的所有数据都已经正确收到。
  4. 确认(ACK)。当ACK=1时ack字段才有效,当ACK=0时,ack字段无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1。
  5. 同步(SYN)。在连接建立时用来同步序号。当SYN=1、ACK=0时,表明这是一个连接请求报文,对方若同意建立连接,则应当在相应报文中设置SYN=1、ACK=1(表明这是一个连接接受报文)。因此,SYN=1就表明这是一个连接请求或连接接受报文。
  6. 终止(FIN)。用来释放一个连接。当FIN=1时,表名此报文段的发送方的数据已经发送完毕,要释放运输连接。
  7. 窗口。指接收方目前允许对方发送的数据量(以字节为单位)。之所以要有这个限制,是因为接收方的数据缓存空间(可见“TCP可靠传输的实现”)是有限的。如发送了一个报文段,其确认号是201,窗口值是300,这就是告诉发送方:从201号字节算起,我的接收缓存还可接受300个字节(201~500),你在给我发送数据时必须考虑到这一点。
  8. 校验和。检测TCP数据报在传输过程中是否有错,检测内容包括首部和数据两部分。
  9. 数据偏移。占4位,表示TCP报文段的数据起始处距离TCP报文段的起始处有多远,实际是表示TCP报文段首部的长度。4位最大值是15,每位表示的单位是4字节,所以TCP首部最大长度不能超过60字节,选项程度不能超过40字节。
  10. 选项。首部的可选部分。长度可变,最长可达40字节,即TCP数据包首部长度为20~60字节。里面存储了MSS(最大数据段长度),即发送的数据包的数据段的最大长度。

5.3 TCP连接的建立和释放

请务必弄清楚上节TCP首部格式再看本节。TCP数据传输总共有3各阶段:连接建立、数据传输和连接释放。注意:这里的TCP连接是指两个主机的应用进程之间的TCP连接,而不是主机之间,下面描述可能会省略为两台主机之间的连接,自己清楚就好

5.3.1 建立连接

TCP建立连接的过程叫握手,握手需要在客户和服务器之间交换3个TCP报文段。下面是三报文握手建立TCP连接的过程:

  1. A和B对应的进程的连接都处于CLOSED状态。
  2. B的TCP服务器进程先创建进程控制块TCB,准备接受客户端的连接请求,此时B进入LISTEN状态。
  3. 一次握手。A的应用进程在打算建立TCP连接的时候创建TCB,然后向B发送TCP报文段:SYN=1、seq=x。这时,TCP客户进程进入SYN-SENT(同步已发送)状态。TCP规定,SYN报文段不能携带数据,但要消耗掉一个序号,即序号为x的字节数据就是SYN
  4. 二次握手。B收到连接请求后,如果同意建立连接,就像A发送确认,确认内容为:SYN=1、ACK=1、seq=y、ack=x+1。此时服务器B进入SYN-RCVD(同步收到)状态。
  5. 三次握手。客户端A收到B的确认后,还要向B发送确认,原因下面会举例介绍。确认报文段首部字段内容与上一次B发送确认内容相似,不过去掉了SYN=1。发送完报文段后,客户端A进入ESTABLISHED(连接建立)状态,服务器B在收到A发来的确认报文后也进入ESTABLISHED状态。至此,A的应用进程与B的服务进程的TCP连接正式建立。

第三次握手的原因:

假设A向B发送连接建立请求,但是请求数据在网络中滞留了,A在一段时间没收到B的确认,就会重新发送建立连接的请求。如果第二次请求成功,与B建立了TCP连接,然后又释放了连接,若此时B又收到了滞留在网络中A的第一次连接请求,但B并不知道该请求数据已经过时,于是又给A发送了确认。如果没有第三次握手,此时在B给A发送确认之后TCP连接就已经建立,但A认为并没有向B发送请求,所以直接忽略掉了B的确认,导致A不会通过此连接向B发送消息而B却一直在等待A发送的消息,使得资源浪费。同理,若必须在第三次握手后连接才建立,A在收到B的消息后永远不会回复,所以连接不会建立。

5.3.2 释放连接

数据传输结束后,通信的双方都可以释放连接。现在A和B都处于ESTABLISHED状态。

  1. 若A已经没有要向B发送的数据,则A的应用进程先向B的应用进程发送连接释放报文段,并停止发送数据。发送内容为:FIN=1、seq=u。TCP规定,FIN报文段即使不携带数据,它也消耗掉一个序号。然后A进入FIN-WAIT-1(终止等待1)状态,等待B的确认。
  2. B收到连接释放报文段后即发出确认,然后B就进入了CLOSE-WAIT(关闭连接)状态;A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。
  3. TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭状态,即A已经没有数据要发送了,但B若发送数据,A仍要接收。也就是说,从B到A这个方向的连接并未关闭,这个状态可能会持续一段时间。
  4. 若B已经没有要向A发送的数据,其应用进程就发送连接释放报文段,此时B就进入LAST-ACK(最后确认)状态,等待A的确认。
  5. A在收到B的连接释放报文段后,进入TIME-WAIT(时间等待)状态,必须发出确认。在发送报文段后,若A在2MSL(最长报文段寿命)的时间内没有收到B的重传释放连接报文段,则进入到CLOSED状态,而B在收到A的确认后会立刻进入CLOSED状态,意味着B结束TCP连接的时间要比A早一些

为什么A在发送连接释放报文段后必须要等待2MSL的时间才能进入CLOSED状态?

是为了保证A发送的确认能够正常到达B。如果没有2MSL的时间限制,那么A在发送确认报文之后就进入CLOSEDA状态。此时若发送的确认报文段在传输过程中丢失了,B没有收到A的确认,那B就会重传连接释放报文段,而此时A已经释放了连接,收不到B重传的报文段,也就不会向B发送确认,故B无法正常释放连接进入到CLOSED状态。反过来思考,如果有2MSL的时间限制,A会在2MSL的时间内收到B重传的报文段,继而给出确认,同时刷新2MSL的时间计时,B收到了确认进入CLOSED状态,而A在2MSL的时间内没有收到A的重传也会进入CLOSED状态,进而整个TCP连接被关闭。

5.4 TCP可靠传输的实现

TCP可靠传输主要体现在以下几个方面:

  • 发送确认。对于A发送的TCP报文段,B必须给出确认并在确认报文中指定发送端下次发送报文时的规则。
  • 超时重传。若A没有及时收到B的回复,则会重发上次发送的报文段数据(存储在发送缓存中,详情见下文)。
  • 重复丢弃。见下文介绍。
  • 数据校验。B根据TCP报文段首部的校验和字段来判断数据在传输过程中是否发生错误,是则丢弃,并通知A重传数据。
  • 流量控制。接收端会根据缓存空间大小和网络情况来通知发送端发送数据流量的大小。(TCP头部中的“窗口”值)
  • 拥塞控制。

TCP可靠传输的工作原理

下面将TCP传送的数据单元称为分组。假设A是发送方,B是接收方。

停止等待协议

特点:

  • A每次发送一个分组,只有B收到且给出确认后,A才能发送下一个分组。
  • 超时重传(可能是A发送的数据没被B收到,也可能是A没有收到B的确认)。A每次发送分组时就设置一个超时计时器,如果到期了还没收到确认就重传,收到了就撤销超时计时器。
  • 重复(错误)丢弃。

优缺点:

  • 简单。
  • 信道利用率太低,单线程。

连续ARQ协议

特点:

  • 采用滑动窗口来发送数据,窗口内的数据可以一次性按序号连续发送,不用一个个等待确认。收到一个确认(最前面的)就把滑动窗口后移一格。
  • 采用累积确认。如发送了3,4,5三个分组,B都收到了,然后分别对3,4,5进行了确认,如果3,4的确认丢失了,A只收到了5的确认,表示5前面的都收到了,不用重传3,4。
  • 超时重传。发送的每个分组设置超时计时器。
  • 重复(错误)丢弃。

优缺点:

  • 复杂。
  • 信道利用率高,多线程。

TCP滑动窗口和缓存

以字节为单位的滑动窗口

现假定A收到了B发来的确认报文段,其中窗口是20字节,而确认号是31(表明B期望收到的下一个序号是31,而序号30为止的数据已经收到了)。根据这个数据,A就构造出自己的发送窗口:

发送窗口表示:在没有收到B的下一次确认的情况下,A可以把窗口内的数据都发送出去。

这里说明一下,即A在发送数据时并不是只能一次性把发送窗口内的数据全部发送,而是可以只选择部分字节发送(但是发送字节点必须是从后沿开始连续的一段)。比如上面A在收到B的确认后,将序号为31~33的数据打包发送给B,此时B在接受A发送过来的数据报时会遇到两种情况:

  1. B正常按序收到数据。此时B又会在确认报文中指定新的确认号(ack)和窗口大小,此时确认号为34,假设窗口值依然是20字节,则A的发送窗口会后移,直到所有数据发送完毕,见下面第一张图。
  2. B收到乱序数据。比如数据报在传输的过程中丢失了(或者滞留在网络中)序号为31的字节,只收到了32~33的字节。B在收到后检测到之前序号的字节没有收到,就在确认中将确认号设置为未收到字节的最小序号,即31。下次A发送数据时,依然要从31号开始连续发送,这时B就会收到重复的32~33序号的数据,B检测到重复后就会丢弃。如果B收到的是31~32号的字节,那确认号就是33。

  • 接收端应用程序来不及读取接受到的数据,那接收缓存很快就会被填满,接收方就会在确认中减小窗口值。
  • 滑动窗口的大小不仅仅取决于接收端确认的窗口值,也取决于网络的拥塞程度。见下面拥塞控制。

发送接收缓存

在TCP通信时,发送端有发送缓存,接收端有接收缓存。注意,TCP通信的双方既是发送端,也是接收端,都有发送缓存和接受缓存。他们的作用如下:

  • 发送缓存:用来存即将发送或发送了还没收到确认的数据。
  • 接收缓存:用来暂时存放按需到达但尚未被接收应用程序读取的数据;或未按序到达的数据。

缓存和窗口的关系

TCP流量控制

滑动窗口实现流量控制

通过滑动窗口可以在TCP连接上实现对发送方的流量控制(rwnd和cwnd)。下面rwnd表示窗口值,接收端会根据自己的接受能力修改窗口值。

注意:当B向A发送rwnd=0的零窗口确认后,A就不会再发送常规消息(可以发送零窗口探测报文段、确认报文段和携带紧急数据的报文段),直到收到B的非零窗口确认。所以如果B的非零窗口确认在网络中丢失了(B不会重传确认),那么A和B就会陷入僵持状态。为了解决这种情况,TCP为每一个连接设置了一个持续计时器,当TCP连接的一方收到了零窗口通知,就会启动计时器,当设定的时间到了就会发送一个探测报文段(携带1字节的数据),检测现在的窗口值,如果是0就重置计时器,不是就打破了僵局,继续传输。

TCP里的策略提升传输效率

TCP中采用了某些策略去提升在特定场景下的数据传输效率。

场景1:

  • 问题:当数据在网络中的传输非常快的时候,可能会出现发送缓存还没累积多少数据,就会被立刻发送,导致每次发送的数据非常少,发送次数非常多,降低网络传输的效率。
  • 解决:TCP实现里面使用的是Nagle算法,就是先将发送缓存中的第一个字节发送,收到确认后在将缓存中所有数据组装成一个数据报发送,收到确认后再将缓存中所有数据组装成一个数据报发送,以此类推。

场景2:

  • 问题:接受端缓存满了后,接收端的应用程序每次也只从接收缓存中读取很少的字节(比如1个),那么接收端就要在缓存空间十分有限的情况下向发送端发送确认,导致确认的窗口值很小,这也就影响到了发送端发送的效率。
  • 解决:可以让接受方等待一段时间,等到缓存有足够的空间可以容纳MSS(最长的数据段),或缓存空闲空间为整个缓存的一般时,才发送确认。

TCP拥塞控制

  • 概念:当对网络中某个资源的需求超过了该资源所能提供的上限,网络的性能就要变坏,这种情况就叫拥塞。
  • 产生原因:当大量数据堵塞在某一个节点,就会导致数据超时,从而发生数据的重传,重传的数据会进一步堵塞网络,导致更多的重传,最终导致拥塞。拥塞是由许多原因引起的,数据从源主机发送到目标主机,中间任何地方发生问题都会导致拥塞,类似于“漏桶原理”。比如:某个网络的带宽较低,某个路由器节点的缓存较小或处理器性性能太差等等,都可能导致网络拥塞。
  • 控制原则:要么提升整个网络传输数据的上限,要么降低输入网络的数据量。如要提升网络传输的上限,那么整个网络都要升级,这几乎不可能做到;所以,只能通过降低输入网络的数据量来做拥塞控制
  • 拥塞控制与流量控制的区别:拥塞控制是防止过多的数据注入网络,使网络中的路由器或数据链路不过载,关注的是中间传输过程的控制;流量控制是端对端的控制,控制发送方发送的速率,以便接收端来得及接收。
  • TCP拥塞控制算法:慢开始、拥塞避免、快重传、快恢复。

拥塞判断

  • 超时:表示堵死了,数据发不过去,或者对方的确认发不过来。情况严重,必须要立刻进行拥塞控制。
  • 收到三个重复ACK(分组丢失):表示存在少量分组丢失,其它分组能正常送达。情况不是太严重,可以进行少量拥塞控制。

拥塞控制算法

  • 拥塞避免:TCP发送方通过维持一个拥塞窗口CWND来进行拥塞控制,CWND的具体大小设置见下面实现介绍。

发送端发送的窗口大小 = Min(接收方确认的窗口值rwnd, 拥塞窗口值cwnd)

  • 慢开始:发送窗口由小变大。
  • 快重传:接收方收到发送方的分组后要立刻进行回复,以便当分组丢失时尽快让发送方知道;发送方发现分组丢失后,比如收到了3-ACK,要立刻进行重传。
  • 快恢复:当收到3-ACK时,适当降低cwndssthresh,让传输尽快恢复。而不是直接将cwnd设为1。

拥塞控制实现过程

  1. 检测是否发生拥塞,如果发生了超时,执行2;收到了3-ACK,执行3。
  2. 当发生超时,表示拥塞已经发生,执行“慢开始”算法,令ssthresh=cwnd/2,cwnd=1,如果能收到确认,则翻倍增长,1-2-4-8-16......,当增长到ssthresh(门限值)时,窗口变为每次+1,直到发生超时或收到3-ACK。
  3. 当收到3-ACK时,表示某个分组丢失,网络条件开始变差,要预防拥塞产生。此时执行快恢复”(令ssthresh=cwnd/2,cwnd=ssthresh快重传”(在下一轮立刻进行重传算法,因为cwnd=ssthresh,所以窗口每一轮只增加1个单位。直到发生超时或收到3-ACK

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值