【编程者必会系列】:TCP/IP之传输层

2022-11-30 16:56:59 浏览数 (1)

计算机网络是计算机基础知识的重点,不管你是C 还是JAVA,安卓还是IOS,都必须要会的基础知识。今天学习的就是TCP/IP的传输层知识点总结,很多知识点将来面试中都会问到,值得学习!

/**

本篇博客由汗青ZJF整理并发布, 转载请注明出处:

http://blog.csdn.net/zjf280441589/article/category/1854365

*/

传输层的主要功能

    1)传输层为应用进程之间提供端到端的逻辑通信(网络层是为主机到主机提供逻辑通信)。

    2)复用和分用: 复用是指发送方不同的应用进程都可以使用同一个传输层协议传送数据; 分用是指接收方的传输层在剥去报文的首部之后能够把这些数据正确交付到目的应用进程.

    3)传输层还会对收到的报文进行差错检测(首部和数据部分), 而网络层只检查IP数据报的首部, 不检验数据部分是否出错。

    4)传输层需要有两种不同的运输协议:面向连接的传输控制协议 TCP (Transmission Control Protocol)和无连接的用户数据报协议 UDP (User Datagram Protocol);

流量控制与拥塞控制的区别

    流量控制往往是指在发送端和接收端之间的点对点通信量的控制. 流量控制所要做的是抑制发送端发送数据的速率, 以便使接收端来得及接收; 而拥塞控制必须确保通信子网能够传送待传送的数据, 是一个全局性的问题, 涉及网络中所有的主机、路由器以及导致网络传输能力下降的所有因素.

端口

    端口就是传输层的服务访问点, 用一个 16位的数字进行标标记。

    端口号只具有本地意义,即端口号只是为了标志本计算机应用层中的各进程。在因特网中不同计算机的相同端口号是没有联系的。

    端口的作用是让应用层的各种应用进程都能将其数据通过端口向下交付给传输层,以及让传输层知道应当将其报文段中的数据向上通过端口交付给应用层的哪个进程。

    从这个意义上讲,端口是用来标志应用层的进程;

常用端口号

应用程序

echo

ftp

ssh

telnet

smtp

端口号

7

20,21

22

23

25

应用程序

dns

dhcp

tftp

http

pop3

端口号

53

67, 68

69

80

110

TCP VS UDP

1)TCP

    TCP是一种面向连接的(一对一),提供可靠交付的和全双工通信的,基于字节流的端到端传输层通信协议。

    面向连接: TCP在传输数据之前必须先建立连接,数据传输结束后要释放连接。

    一对一: 每一条TCP连接只能有2个端点,故TCP不提供广播或多播服务。

    可靠交付: TCP提供可靠交付,通过TCP连接传输的数据,无差错、不丢失、不重复、并且按序到达。

    基于字节流: TCP是面向字节流的。虽然应用进程和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流, 而并不知道所传输的字节流的含义。

2)UDP

    UDP是一种无连接的,尽最大努力交付的和全双工通信的,基于报文段的端到端传输层通信协议。

    无连接: UDP在发送数据之前不需要建立连接

    尽最大努力交付: UDP不保证可靠交付,主机不需要维持复杂的连接状态

    面向报文: UDP是面向报文的。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的的边界,即应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。在接收端,UDP一次交付一个完整的报文, 因此应用程序需要选择合适的报文大小。

其他:

    UDP没有拥塞控制,网络出现的拥塞不会使源主机的发送速率降低。

    UDP支持一对一、一对多、多对一和多对多的交互通信。

    UDP的首部开销小,只有8个字节,比TCP的20个字节的首部要短。

3)区别

TCP

UDP

面向连接

无连接

传输速度慢

传输速度快

保证数据有序到达

不保证数据有序到达

保证数据正确性

可能丢包

TCP报文段

UDP用户数据报

系统资源要求多(需要内核维护发送/接受缓冲区)

要求少(不需要内核维护缓冲区, 直接将数据报发送到网络上, 或直接交付给进程)

适用于对效率要求相对低,但对准确性要求相对高的场景下,或者是有一种连接概念的场景(如HTTP服务)

适用于对效率要求相对高,对准确性要求相对低的场景(如视频点播)

UDP数据报

UDP有两个字段: 首部字段和数据字段。

首部字段很简单,只有8个字节,由4个字段组成,每个字段的长度都是两个字节。

源端口号

在需要对方回信时选用。不需要时可用全0

目的端口号

这在终点交付报文时必须要使用到

UDP长度

UDP用户数据报的长度,其最小值是8(仅有首部)

UDP校验和

检测UDP用户数据报在传输中是否有错。有错就丢弃

UDP校验

    UDP首部中校验和的计算方法有些特殊。在计算校验和时,要在UDP用户数据报之前增加12个字节的伪首部。伪首部既不向下传送也不向上递交,而仅仅是为了计算校验和。与IP数据报的校验和只校验IP数据报的首部不同,UDP的校验和是把首部和数据部分一起都校验。

    在计算检验和时,临时把“伪首部”和 UDP 用户数据报连接在一起。伪首部仅仅是为了计算检验和, 示例如下:

    在发送方,首先是把全零放入校验和字段并且添加伪首部。然后,把UDP数据报看成是由许多16位的字串连接起来。若UDP数据报的数据部分不是偶数个字节,则要在数据部分末尾增加一个全零字节(但此字节不发送)。接下来就按二进制反码计算出这些16位字的和。将此和的二进制反码写入校验和字段。在接收方,把收到的UDP数据报加上伪首部(如果不为偶数个字节,还需要补上全零字节)后,按二进制反码计算出这些16位字的和。当无差错时其结果应全为1。否则就表明有差错出现,接收方就应该丢弃这个UDP数据报。

TCP报文段

协议描述

源端口/目的端口

源/目的主机的IP地址加上端口号构成一个TCP连接(Socket)

序号和确认号

序号为该TCP数据包的第一个字节在所发送的数据流中的偏移量;确认号为希望接收的下一个数据字节的序号;

数据偏移(首部长度)

以4个字节为单位,通常为20个字节

6个标志位:

URG

如果使用了紧急指针,URG置1,紧急指针为当前序号到紧急数据位置的偏移量(常用于发送/接受带外数据)

ACK

为1表示确认号有效,为0表示该TCP数据包不包含确认信息

PSH

表示是带有PUSH标志的数据,接收到数据后不必等缓冲区满再发送(较少使用)

RST

置为1时表示TCP连接中出现了严重的差错, 必须释放连接, 然后重建连接, 也可用于拒绝非法的数据或拒绝连接请求

SYN

用于建立连接,连接请求时SYN=1,ACK=0;响应连接请求时SYN=1,ACK=1

FIN

用于释放连接,表示发送方已经没有供发送的数据

窗口大小

用来让对方设置发送窗口的大小(用于流量控制)

校验和

校验和覆盖了整个数据包,包括对数据包的首部和数据

紧急指针

指出本报文段中紧急指针共占用多少个字节(紧急数据放在本报文段数据的最前面)

选项

常见的选项是MSS(Maximum Segment Size, 最大报文长度)

填充字段

为了使整个首部为4字节整数倍

TCP三次握手

为什么需要采用三次握手?

    主要是为了防止两次握手情况下已失效的连接请求报文段突然又传送到服务端,而产生的错误。举例如下:

    客户A向服务器B发出TCP连接请求,第一个连接请求报文在网络的某个节点长时间滞留,A超时后认为报文丢失,于是再重传一次连接请求,B收到后建立连接。数据传输完毕后双方断开连接。而此时,前一个滞留在网络中的连接请求到达了服务端B,而B认为A又发来连接请求,若采用的是“两次握手”,则这种情况下B认为传输连接已经建立,并一直等待A传输数据,而A此时并无连接请求,因此不予理睬,这样就造成了B的资源白白浪费了;但此时若是使用“三次握手”,则B向A返回确认报文段,由于是一个失效的请求,因此A不予理睬,建立连接失败。第三次握手的作用:防止已失效的连接请求报文段突然又传送到了服务器。

三次握手过程

    1)第一次握手:客户机的TCP首先向服务器的TCP发送一个连接请求报文段。这个特殊的报文段中不含应用层数据,其首部中的SYN标志位被置为1。另外,客户机会随机选择一个起始序号seq=x(连接请求报文不携带数据,但要消耗掉一个序号)。

    2)第二次握手:服务器的TCP收到连接请求报文段后,如同意建立连接,就向客户机发回确认,并在OS内核中为该TCP连接分配TCP缓存和变量。在确认报文段中,SYN和ACK位都被置为1,确认号字段的值为x 1(表示希望收到的下一个字节的序号为x 1),并且服务器随机产生起始序号seq=y(确认报文不携带数据,但也要消耗掉一个序号)。

    3)第三次握手:当客户机收到确认报文段后,还要向服务器给出确认,并且也要在client端的OS内核中给该连接分配缓存和变量。这个报文段的ACK标志位被置1,序号字段为x 1,确认号字段为y 1。

    需要注意的是:服务器端的资源是在完成第二次握手时分配的,而客户端的资源是在完成第三次握手时分配的。这就使得服务器易于受到SYN洪泛攻击。

TCP四次断开

    1)第一次断开:客户机打算关闭连接,就向其TCP发送一个连接释放报文段,并停止发送数据,主动关闭TCP连接,该报文段的FIN标志位被置1,seq=u,它等于前面已传送过的数据的最后一个字节的序号加1(FIN报文段即使不携带数据,也要消耗掉一个序号)。

    2)第二次断开:服务器收到连接释放报文段后即发出确认,确认号是ack=u 1,而这个报文段自己的序号是v,等于它前面已传送过的数据的最后一个字节的序号加1。此时,从客户机到服务器这个方向的连接就释放了,TCP连接处于半关闭状态。但服务器若发送数据,客户机仍要接收,即从服务器到客户机这个方向的连接并未关闭。

    3)第三次断开:若服务器已经没有要向客户机发送的数据,就通知TCP释放连接,此时其发出FIN=1的连接释放报文段(注意: 此时确认号字段值仍为u 1, 因为这段时间里, 客户端并未发送任何数据到服务器)。

    4)第四次断开:客户机收到连接释放报文段后,必须发出确认。在确认报文段中,ACK字段被置为1,确认号ack=w 1,序号seq=u 1。此时TCP连接还没有释放掉,必须经过时间等待计时器设置的时间2MSL后,A才进入到连接关闭状态。

TIME_WAIT状态

    1)为了保证客户端发送的最后一个ACK报文段能够达到服务器。 这个ACK报文段可能丢失,因而使处在LAST_ACK状态的服务器收不到确认。这样的话, 服务器会超时重传FIN ACK报文段,客户端就能在2MSL时间内收到这个重传的FIN ACK报文段,接着客户端重传一次确认,重启计时器。最后,客户端和服务器都正常进入到CLOSED状态。

    如果客户端在TIME_WAIT状态不等待一段时间,而是在发送完ACK报文后立即释放连接,那么就无法收到服务器重传的FIN ACK报文段,因而也不会再发送一次确认报文。这样,服务器就无法按照正常步骤进入CLOSED状态。

    2)防止已失效的连接请求报文段出现在本连接中。客户端在发送完最后一个ACK确认报文段后,再经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。

    注意:服务器结束TCP连接的时间要比客户端早一些,因为客户机(最先提出close请求的一端)最后要等待2MSL后才可以进入CLOSED状态。

TCP如何保证可靠性

序号: TCP连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号;

确认: TCP首部的确认号是期望收到对方的下一个报文段数据的第一个字节的序号。当数据发送出去之后, 发送方缓存区会继续存储那些已经发送但未收到确认的报文段,以便在需要的时候重传。TCP默认使用累计确认,即TCP只确认数据流中至第一个丢失字节为止的字节。

重传: 有两种事件会导致TCP对报文段进行重传:超时和冗余ACK。

        1)超时: TCP每发送一个报文段,就对这个报文段设置一次计时器。只要计时器设置的重传时间到期但还没有收到确认,就要重传这一报文段。

        2)冗余ACK(冗余确认): 冗余ACK就是再次确认某个报文段的ACK,而发送方先前已经收到过该报文段的确认; TCP规定当发送方收到对同一个报文段的3个冗余ACK时,就可以认为跟在这个被确认报文段之后的报文段已经丢失;

校验: TCP将保持它首部和数据的校验和。这是一个端到端的校验和,目的是检测数据在传输过程中的任何变化。如果收到段的校验和有差错,TCP将丢弃这个报文段并且不确认(导致对方超时重传);

重排: TCP承载于IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。TCP将对收到的数据进行重新排序。IP数据报会发生重复,TCP的接收端会丢弃重复的数据。

流量控制: TCP还能提供流量控制。TCP连接的每一方都有一定大小的缓冲空间。

分割: 应用数据被分割成TCP认为最适合发送的数据块,称为TCP报文段传递给IP层。

滑动窗口协议与停止等待协议的区别

    滑动窗口协议中,允许发送方发送多个分组(当有多个分组可用时), 而不需等待确认,但它受限于在流水线中未确认的分组数不能超过某个最大允许数N。

    滑动窗口协议是TCP使用的一种控制流量的方法,此协议能够加速数据的传输。 只有在接收窗口向前滑动时(与此同时也发送了确认), 发送窗口才有可能向前滑动。收发两端的窗口按照以上规律不断地向前滑动,因此这种协议称为滑动窗口协议。

    当发送窗口和接收窗口的大小都等于1时,就是停止等待协议。

TCP流量控制

    TCP提供了流量控制服务以消除发送方使接收方缓存区溢出的可能性,因此可以说流量控制是一个速度匹配服务(匹配发送方的发送速率与接收方的读取速率)。

    在通信过程中,接收方根据自己接收缓存的大小,动态地调整发送方的发送窗口大小,这就是接收窗口rwnd,即调整TCP报文段首部中的“窗口”字段值,来限制发送方向网络注入报文的速率。同时,发送方根据其对当前网络拥塞程序的估计而确定的窗口值,称为拥塞窗口cwnd,其大小与网络的带宽和时延密切相关。

滑动窗口

    TCP 采用大小可变的滑动窗口进行流量控制(窗口大小的单位是字节), 在 TCP 报文段首部的窗口字段写入的数值就是当前给对方设置的发送窗口数值的上限。

    发送窗口在连接建立时由双方商定。但在通信的过程中,接收端可根据自己的资源情况,随时动态地调整对方的发送窗口上限值(可增大或减小)。

发送过程及详细分析

    1)发送端要发送 900 字节长的数据,划分为 9 个 100 字节长的报文段,而发送窗口确定为 500 字节。 发送端只要收到了对方的确认,发送窗口就可前移。发送 TCP 要维护一个指针。每发送一个报文段,指针就向前移动一个报文段的距离。

    2)发送端已发送了 400 字节的数据,但只收到对前 200 字节数据的确认,同时窗口大小不变。现在发送端还可发送 300 字节(401~700)。

    3)发送端收到了对方对前 400 字节数据的确认,但对方通知发送端必须把窗口减小到 400 字节。现在发送端最多还可发送 400 字节(401~800)的数据。

利用可变窗口大小进行流量控制(双方确定的窗口值是 400)

(101~200的数据发生丢失)

慢开始和拥塞避免

1. 发送端的主机在确定发送报文段的速率时,既要根据接收端的接收能力,又要从全局考虑不要使网络发生拥塞。因此,每一个 TCP 连接需要有以下两个状态变量:

    接收窗口 rwnd (receiver window): 这是接收端根据其目前的接收缓存大小所许诺的最新的窗口值,是来自接收端的流量控制。接收端将此窗口值放在 TCP 报文的首部中的窗口字段,传送给发送端。

    拥塞窗口 cwnd (congestion window): 是发送端根据自己估计的网络拥塞程度而设置的窗口值,是来自发送端的流量控制。

    发送端的发送窗口的上限值应当取为接收端窗口 rwnd 和拥塞窗口 cwnd 这两个变量中较小的一个,即应按以下公式确定:

发送窗口的上限值 = Min(rwnd, cwnd)

2. 慢开始算法

    在TCP刚刚连接好,开始发送TCP报文段时,先令拥塞窗口cwnd=1,即一个最大报文段长度MSS。而在每收到一个对新的报文段的确认后,将cwnd加1,即增大一个MSS。用这样的方法逐步增大发送方的拥塞窗口cwnd,可以使分组注入到网络的速率更加合理。

    使用慢开始算法后,每经过一个传输轮次(即往返时延RTT),拥塞窗口cwnd就会加倍,即cwnd的大小呈指数形式增长(可以看出”慢开始”并不”慢”)。这样慢开始一直把拥塞窗口cwnd增大到一个规定的慢开始门限ssthresh(阈值),然后改用拥塞避免算法。

3. 拥塞避免算法

    发送端的拥塞窗口cwnd每经过一个往返时延RTT就增加一个MSS的大小,而不是加倍(不同于慢开始算法),使cwnd按线性规律缓慢增长(即加法增大),而当出现一次超时(网络拥塞)时,则令慢开始门限ssthresh等于当前cwnd的一半(即乘法减小)。

根据cwnd的大小执行不同的算法,可归纳如下:

        当cwnd<ssthresh时,使用慢开始算法。

        当cwnd>ssthresh时,停止使用慢开始算法而改用拥塞避免算法。

        当cwnd=ssthresh时,既可使用慢开始算法,也可使用拥塞避免算法(通常做法)。

4.网络拥塞的处理

    当网络出现拥塞时,无论在慢开始阶段还是在拥塞避免阶段,只要发送方检测到超时事件的发生(没有按时收到确认,重传计时器超时),就要把慢开始门限ssthresh设置为出现拥塞时的发送方cwnd值的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。

    拥塞避免并非完全能避免拥塞。利用以上措施要完全避免网络拥塞是不可能的。拥塞避免是指在拥塞避免阶段把拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞。

    慢开始和拥塞避免算法的实现过程如下图所示:

    注意,在慢开始(指数级增长)阶段,若2*cwnd>ssthresh,则下一个RTT的cwnd应等于ssthresh,而不是2*cwnd,即cwnd不能跃过ssthresh值。

小结:

    在慢开始和拥塞避免算法中使用了“乘法减小”和“加法增大”方法。“乘法减小”是指不论在慢开始阶段还是拥塞避免阶段,只要出现一次超时(即很可能出现了网络拥塞),就把慢开始门限值ssthresh设置为当前的拥塞窗口值的一半。当网络频繁出现拥塞时,ssthresh值就下降得很快,以大大减少注入到网络中的分组数。而“加法增大”是指执行拥塞避免算法后,在收到对所有报文段的确认后(即经过一个RTT),就把拥塞窗口cwnd增加一个MSS大小,使拥塞窗口缓慢增大,以防止网络过早出现拥塞。

快重传与快恢复

    快重传和快恢复算法是对慢开始和拥塞避免算法的改进。

1.快重传

    当发送方连续收到三个重复的ACK报文时,直接重传对方尚未收到的报文段,而不必等待那个报文段设置的重传计时器超时。

2.快恢复

    快恢复算法原理:当发送端收到连续三个冗余ACK(即重复确认)时,就执行“乘法减小”算法,把慢开始门限ssthresh减半。与慢开始(慢开始算法将拥塞窗口cwnd设置为1)不同之处是它把cwnd的值设置为慢开始门限ssthresh减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大。

    由于跳过了cwnd从1起始的慢开始过程(因为既然现在能够收到三个重复ACK确认, 就说明拥塞程序并不是很大),所以被称为快恢复。快恢复算法的实现过程如下图所示,作为对比,虚线为慢开始的处理过程。

注-发送方发送窗口的实际大小由流量控制和拥塞控制共同决定。因此,当同时出现了接收端窗口(rwnd)和拥塞窗口(cwnd)时,发送方实际的发送窗口大小是由rwnd和cwnd中较小的那一个确定的。

0 人点赞