1、传输层概述
1.1、传输层
为应用层提供通信服务,使用网络层服务
1)功能
-
传输层提供进程和 进程之间 的逻辑通信
网络层提供 主机之间 的逻辑通信
-
复用和分用
例如一家四口都要给好友写信,统一放到邮筒里,邮政员一起送出去,这是复用。收到回信后,快递员把信分别给我们,这是分用。快递员就充当了传输层的角色。
-
传输层对收到的报文进行 差错检测
网络层学过首部校验和,但是首部校验和只是校验首部,没有校验数据部分。因此需要传输层 对数据进行检错。可以看出,传输层和网络层一起实现了可靠传输。但是传输层不一定实现可靠传输,要看是哪种协议
-
传输层的两种协议:TCP、UDP
2)两个协议
打油诗:传输层有两个好兄弟,大哥TCP和二弟UDP,大哥靠谱,二弟不靠谱。
-
面向连接的传输控制协议TCP
- 传送数据之前必须建立连接,数据传送结束后要释放连接
- 不提供广播或多播服务
- 由于TCP要提供可靠的面向连接的传输服务,因此不可避免增加了许多开销:确认、流量控制、计时器及连接管理等
- 可靠,面向连接,时延大,适用于大文件
-
无连接的用户数据报协议UDP
- 传送数据之前不需要建立连接,收到UDP报文后也不需要给出任何确认
- 不可靠,无连接,时延小,适用于小文件。例如微信发信息
1.2、传输层的寻址与端口
-
复用:应用层所有的应用进程都可以通过传输层,再传输到网络层
-
分用:传输层从网络层收到数据后,交付给指明的应用进程
-
通信过程分析
如果要发送数据给一个主机,只需要知道它的IP地址,就能寻找到主机所在的网络;进入所在网络后可以根据MAC地址定位到具体的主机(网络层);找到主机后,还需要找到主机中接收该数据的进程(传输层)。如何找到该进程呢?——根据 端口(逻辑端口)
-
端口:端口是传输层的 SAP(服务访问点/接口),标识主机中的应用进程
该端口为逻辑端口/软件端口,要和硬件端口区分开,像路由器、交换机这种直接插上去的端口称为硬件端口
-
端口号:端口由具体的数字标识叫做端口号,端口号 只有本地意义,在因特网中不同计算机的相同端口是没有联系的
-
端口号范围
端口号长度为16bit,能表示2^16=65536个不同的端口号
TFTP( 简单文件传输协议:Trivial):69岁退休
SNMP(简单网络管理协议:Simple Network Management Protocol):在161医院要死了。
- 套接字
- 在网络中采用发送方和接收方的套接字组合来识别端点,套接字 唯一标识 了网络中的一个主机(IP地址标识网络中每一个主机)和它上面的一个进程(端口号标识主机中的进程)
- 套接字Socket = ( 主机IP地址,端口号):根据IP地址可以找到主机(MAC地址(标识数据链路层上每一个设备/网卡)也是根据IP地址找到的),根据端口号可以找到主机中的具体进程
2、UDP协议
2.1、UDP数据报
UDP(User Datagram Protocol):用户数据报协议
1)UDP概述
UDP只在IP数据报服务之上增加了很少功能,即 复用分用 和 差错检测 功能
UDP的主要特点:
-
UDP是无连接的,减少开销和发送数据之前的时延
-
UDP使用 最大努力交付,即 不保证可靠交付(由应用层保证可靠交付)
-
UDP是 面向报文 的,适合一次性传输 少量数据 的网络应用
应用层给UDP多长的报文,UDP就照样发送,即一次发一个完整报文。在传输层称为报文段。如果数据太大,在传给网络层时还要分片,所以适合一次传输少量数据
-
UDP 无拥塞控制,适合很多 实时应用
-
UDP首部开销小,首部大小为 8B。而TCP首部为 20B
2)UDP首部格式
UDP首部字段(8B)
- 源端口号:可有可无,在需要对方回信时选用。不需要时可用全0
- 目的端口号:在终点交付报文时必须要使用到
- UDP长度:UDP数据报的长度(包括 首部和数据),其最小值是8B(仅有首部)
- UDP校验和:检验UDP数据报在传输中是否有错。有错就丢弃。该字段是可选的,当源主机不想计算校验和时,则直接令该字段为全0
还有一种出错情况:分用时,找不到对应的目的端口号,就丢弃报文,并给发送方发送 ICMP“端口不可达” 差错报告报文
2.2、UDP校验
伪首部:伪首部只有在计算检验和时才出现,不向下传送也不向上递交。伪首部 伪的就是IP数据报的首部
- 0字段:固定部分,全0
- 17字段:封装UDP报文的IP数据报首部协议字段是17。(IP数据报首部的协议字段,说明数据部分使用的是什么协议)
- UDP长度:UDP首部8B + 数据部分长度(不包括伪首部)
如何用伪首部校验UDP数据报有没有发送差错
在发送端:
-
填上伪首部(伪首部只有在计算检验和时才出现)
-
先首部校验和字段填充全0
-
全0填充数据部分(目的是要让UDP数据报要看成许多4B的字串接起来)
-
伪首部 + 首部 + 数据部分采用 二进制反码求和(此时校验和字段全0)
-
把 和 求反码 填入检验和字段
-
去掉伪首部,发送
二进制反码求和具体来说就是:
0+0=0
1+0=0+1=1
1+1=10
其中10中的1加到了下一列去,如果是最高列的1+1,那么得到的10留下0,1移到最低列,与最低位再做一次二进制加法即可
在接收端:
- 填上伪首部
- 伪首部 + 首部 + 数据部分采用二进制反码求和(此时校验和字段有值)
- 结果全为1则无差错,否则丢弃数据报/交给应用层附上出差错的警告
3、TCP协议
TCP(Transmission Control Protocol):传输控制协议
3.1、TCP协议特点和报文段
1)协议特点
-
TCP是 面向连接 (虚连接,并不是物理连接)的传输层协议。打call
-
每一条TCP连接只能有两个端点,每一条TCP连接只能是 点对点 的(无法用于广播或多播)
-
TCP提供 可靠交付 的服务,无差错、不丢失、不重复、按序到达。可靠有序,不丢不重
-
TCP提供 全双工通信
- 发送缓存:准备发送的数据&已发送但尚未收到确认的数据
- 接收缓存:按序到达但尚未被接受应用程序读取的数据&不按序到达的数据
-
TCP面向 字节流:TCP把应用程序交下来的数据看成仅仅是一连串的无结构的字节流。字节流中的每一个字节都按顺序编号
- 流:流入到进程或从进程流出的字节序列
2)报文段首部格式
重点,单位4B
-
固定首部(20B)
-
源端口:2B
-
目的端口:2B
-
序号seq(sequencer:n. 音序器):4B;
在一个TCP连接中传送的 字节流 中的每一个字节都按顺序编号,本字段表示本报文段所发送数据的第一个字节的序号。(一起来吃饭的一组人按顺序每个人分个号,但进去的时候只看第一个人的序号)
TCP头就是TCP首部,序号字段表示的是报文段中 第一个字节的序号
-
确认号ack:4B
期望 收到对方 下一个报文段的第一个数据字节的序号。若确认号为N,则证明到序号N-1为止的所有数据都已正确收到。(服务员确认一下下一组人的第一个人是几号)
-
数据偏移(首部长度) : 4位
TCP报文段的数据起始处 距离 TCP报文段的起始处 有多远,以 4B位单位,即1个数值是4B。 例如数据偏移是1111,10进制数是15,15*4B=60B。说明TCP首部长度为60B
-
6个控制位
- 紧急位URG(urgency:n紧急):URG=1时, 标明此报文段中有紧急数据,是高优先级的数据,应尽快传送,不用在缓存里排队,配合紧急指针字段使用。(这组人有会员,先进去)
- 确认位ACK:ACK=1时确认号有效,在连接建立后所有传送的报文段都必须把ACK置为1。(拿到号后,服务员必须给号盖章)
- 推送位PSH:PSH=1时, 接收方尽快交付接收应用进程,不再等到缓存填满再向上交付。(进去以后,有一组人很急,要先吃)
- 复位RST(rest:重置):RST=1时,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立传输链接。(之前号码作废,重新取号)
- 同步位SYN(synchronous:同步的): SYN=1时,表明是一个连接请求报文或连接接受报文。(我和服务员说取个号/服务员把号给我)
- 终止位FIN:FIN=1时, 表明此报文段发送方数据已发完,要求释放连接。(一组人已经进去了,号可以作废了)
-
窗口:2B
指的是发送本报文段的一方的接收窗口,即 现在允许对方发送的数据量
-
检验和:2B
检验首部 + 数据,检验时要加上12B伪首部,第四个字段为6
-
紧急指针:2B
URG = 1 时才有意义,指出本报文段中紧急数据的字节数。(是会员时,查看会员人数)
-
-
选项(长度可变):最大报文段长度MSS、窗口扩大、时间戳、选择确认...
-
填充:全0,保证TCP首部是4B的倍数,填充+选项=4B
3.2、TCP连接管理
TCP连接传输三个阶段:连接建立——数据传送——连接释放
1)TCP连接建立 (三次握手)
TCP连接的建立采用 客户/服务器 方式,主动发起连接建立的应用进程叫做 客户,而被动等待连接建立的应用进程叫 服务器
假设运行在一台主机(客户)上的一个进程想与另一台主机(服务器)上的一个进程建立一条连接,客户应用进程首先通知客户TCP,他想建立一个与服务器上某个进程之间的连接,客户中的TCP会用以下步骤与服务器中的TCP建立一条TCP连接:
TCP连接建立过程:
- ROUND 1:
客户端发送 连接请求 报文段,无应用层数据
-
SYN=1(同步位:SYN=1时,表明是一个连接请求/连接接受报文)
-
seq=x(序号字段:随机分配,表示连接请求报文段第一个字节的序号)
-
ROUND 2:
服务器端为该TCP连接分配缓存和变量,并向客户端 返回确认报文段,允许连接,无应用层数据
- SYN=1
- ACK=1(确认位:ACK=1时确认号有效,连接建立后所有传送的报文段都必须把ACK置为1)
- seq=y(序号字段:随机分配,确认报文段也有序号字段)
- ack=x+1(确认号字段:因为客户端的连接请求报文段第一个字节的序号为x,表示期待客户端接下来的发送报文段的第一个字节的序号为x+1)
-
ROUND 3:
客户端为该TCP连接分配缓存和变量,并向服务器端 返回确认的确认报文段,可以 携带数据
- SYN=0(发送连接请求报文/连接接受报文时SYN才为1)
- ACK=1(确认位:ACK=1时确认号有效,连接建立后所有传送的报文段都必须把ACK置为1)
- seq=x+1(序号字段:因为客户端之前的连接请求报文段第一个字节序号为x,下一个发送报文段就是x+1)
- ack=y+1(确认号字段:因为服务端上次发来的确认报文段第一个字节序号是y,所以期待下一个服务端确认报文段的第一个字节的序号为y+1)
2)SYN洪泛攻击
SYN洪泛攻击发生在OSl第四层,这种方式利用TCP协议的特性,就是三次握手。攻击者发送TCP SYN,SYN是TCP三次握手中的 第一个数据包, 而当服务器返回ACK后, 该攻击者就 不对其进行再确认,那这个TCP连接就处于 挂起状态,也就是所谓的 半连接状态,服务器收不到再确认的话,还会重复发送ACK给攻击者。这样更加会浪费服务器的资源。攻击者就对服务器发送非常大量的这种TCP连接,由于每一个都没法完成三次握手,所以在服务器上,这些TCP连接会因为挂起状态而消耗CPU和内存,最后服务器可能死机,就无法为正常用户提供服务了。
解决办法:设置SYN cookie
3)TCP连接释放 (四次挥手)
参与一条TCP连接的两个进程中的任何一个都能终止该连接,连接结束后,主机中的“资源”(缓存和变量) 将被释放
-
ROUND 1:
客户端 发送 连接释放报文段,停止发送数据,主动关闭TCP连接
- FIN=1(终止位:FIN=1时, 表明客户端数据已发完,要求释放连接。)
- seq=u(序号字段:客户端发送的连接释放报文段的第一个字节序号为u,随机分配)
-
ROUND 2:
服务器端 回送一个 确认报文段,客户到服务器这个方向的连接就释放了一一但目前只处于 半关闭状态,因为服务器还可以发送数据
- ACK=1(确认位:ACK=1时确认号有效)
- seq=v(序号字段:服务端发送的确认报文段的序号为v,随机分配)
- ack=u+1(确认号字段:客户端上次发来的连接释放报文段序号是u,期待客户端的下一个数据报的序号是u+1)
-
ROUND 3:
服务器端 发完数据,就发出 连接释放报文段,主动关闭TCP连接
- FIN=1(终止位:FIN=1时, 表明服务端数据已发完,要求释放连接)
- ACK=1
- seq=w(序号字段:服务端发送的连接释放报文段的序号为w,因为这个报文段又是服务端自己发送的,所以序号又要随机分配)
- ack=u+1(确认号字段:为什么和确认报文段一样呢?因为客户端没发送数据,所以继续期待客户端的下一个数据报的序号是u+1)
-
ROUND 4:
客户端 回送一个 确认报文段,再等到时间等待计时器设置的 2MSL (最长报文段寿命)后,连接彻底关闭
- ACK=1
- seq=u+1(序号字段:客户端回送的确认报文段的序号为u+1,正如服务端期待的一样)
- ack=w+1(确认号字段:服务端上次发来的连接释放报文段序号是w,期待服务端的下一个数据报的序号是w+1)
注:
确认号字段是对【对方数据报序号】的下一个期待
序号字段第一次由自己随机分配序号,在之后的互相发送过程中,序号字段按照对方期待的来填写
3.3、TCP可靠传输
传输层:使用TCP实现可靠传输(UDP依靠应用层实现可靠传输)
网络层:提供尽最大努力交付,不可靠传输
可靠:保证接收方进程从缓存区读出的字节流与发送方发出的字节流是完全一样的
1)四种机制
1、校验
与UDP校验一样,增加 伪首部,通过使用 二进制反码求和 的方法来判断是否发生错误
2、序号
虽然我们说TCP是面向字节流的,但是实际发送时,是把一些字节放一起组成报文段。报文段大小是不定的
3、确认
- 发送方如何知道接收方正确完整接收到123报文段呢? —— 确认机制
- 接收方接收报文段后会返回一个确认报文段(首部确认号字段为4,期待下一个字节序号是4)。发送方收到确认报文段后,知道接收方正确接收了,就可以把123报文段从TCP缓存中删去。
- 发送方继续发送456、78报文段,而456报文段没到达接收方,TCP使用累计确认,所以接收方确认报文段的首部确认号字段仍然为4
- 发送方接收到确认报文段后,会重传456报文段。接收方收到456报文段后,给发送方发送首部确认号为9的确认报文段
4、重传
- 确认重传不分家,TCP发送方在 规定时间(重传时间)内没有收到确认,就要重传已发送的报文段。超时重传
- TCP采用 自适应算法,动态改变重传时间 RTTs (加权平均往返时间)
- 发送第一个报文段时,RTTs取的是第一个报文段的RTT(从它发送到收到确认的时间);然后取第二个报文段的RTT......通过公式可以动态计算各报文段加权平均往返时间
有没有什么办法,在超时时间发生之前,就知道发送方有没有丢失报文段,可以尽快重传?
—— 冗余ACK(冗余确认)
冗余ACK(冗余确认):
每当比期望序号大的 失序报文段 到达时,发送一个 冗余ACK,指明下一个期待字节的序号
举例:发送方已发送1,2,3,4,5报文段
- 接收方收到1,返回给1的确认(确认号为2的第一个字节)
- 接收方收到3,仍返回给1的确认(确认号为2的第一个字节) :可以看到,如果发生了失序,还是按照失序前返回确认。
- 接收方收到4,仍返回给1的确认(确认号为2的第一个字节)
- 接收方收到5,仍返回给1的确认(确认号为2的第一个字节)
- 发送方收到3个对于报文段1的冗余ACK ——> 认为2报文段丢失,重传2号报文段。称为快速重传技术
2)TCP的窗口和协议
滑动窗口,停等协议、GBN协议、SR协议等在链路层已经讲过,原理差不多。根据上面所讲的冗余确认可以看出,TCP常使用的是GBN、SR协议
3.4、TCP流量控制
发送窗口 SWND (Send Window)
接收窗口 RWND (Receiver Window)
拥塞窗口 CWND(Congestion Window)
1)流量控制
流量控制:让发送方慢点,要让接收方来得及接收
- TCP利用 滑动窗口机制 实现流量控制
- 在通信过程中,接收方根据自己 接收缓存的大小,动态地调整发送方的 发送窗口大小,即接收窗口rwnd (接收方设置确认报文段的 窗口字段 来将rwnd通知给发送方),发送方的发送窗口取 接收窗口rwnd 和 拥塞窗口cwnd 的最小值
2)流量控制过程
A向B发送数据,连接建立时,B告诉A:“ rwnd=400 (字节)”,设每一个报文段100B,报文段序号初始值为1
- TCP采用的是 累计确认,并不使用停等协议。主机A给B发送了几个报文段,主机B才给A发送一个确认报文段。TCP流量控制可以看做 累计确认 + SR选择重传协议 + 动态调整接收窗口
主机B给主机A发送确认报文段中窗口字段为rwnd=0(零窗口)时,主机A不能再发送数据给主机B,而主机B又在等主机A发送数据,于是主机A和B互相死等,此时就会造成类似操作系统中的死锁现象。如何解决?
—— 持续计时器
3)持续计时器
- TCP为每一个连接设有一个持续计时器,只要TCP连接的一方收到对方的 零窗口通知,就启动持续计时器
- 若持续计时器设置的时间到期,就发送一个零窗口 探测报文段。接收方收到探测报文段时给出 现在的窗口值
- 若窗口仍然是0, 那么发送方就重新设置持续计时器
- 在持续计时器设置的时间内,接收方有可能会给发送方一个非零窗口通知
3.5、TCP拥塞控制
1)拥塞控制
-
出现拥塞的条件:对资源需求的总和 > 可用资源
-
拥塞导致的问题:网络中有许多资源同时呈现供应不足 ——> 网络性能变坏 ——> 网络吞吐量将随输入负荷增大而下降
-
拥塞控制目的:防止过多的数据注入到网络中。这是一个全局性问题
-
拥塞控制与流量控制的区别
- 拥塞控制是多台主机同时使用网络资源给一个接收方发送数据,使得网络非常繁忙,接收方不知道是哪个主机的问题,拥塞控制是一个 全局性 问题
- 流量控制是 点对点 问题,让发送方发慢点
2)拥塞控制四种算法
-
四种算法
-
慢开始、 拥塞避免
-
快重传、 快恢复
-
-
为了方便讨论,假定如下:
-
数据单方向传送,而另一个方向只传送确认(实际传输数据是双向的)
-
接收方总是有足够大的缓存空间,因而发送窗口大小取决于拥塞程度
发送窗口swnd = Min{接收窗口rwnd,拥塞窗口cwnd},这里假设接收窗口足够大,因而发送窗口大小取决于拥塞程度。
-
-
接收窗口 与 拥塞窗口 区别
- 接收窗口:接收方 根据接收缓存设置的值,并告知给发送方,反映接收方容量
- 拥塞窗口:发送方 根据自己估算的网络拥塞程度而设置的窗口值,反映网络当前容量
3)慢开始和拥塞避免算法
-
拥塞窗口最开始的初始值
默认为1即cwnd=1
为了讨论方便,这里1不是一个字节而是一个报文段,报文段的长度是一个最大报文段长度MSS
-
慢开始算法:拥塞窗口指数规律增长,拥塞窗口在发送方收到确认报文时增长
-
ssthresh值:拥塞窗口增加到ssthresh(慢开始限值)的初始值后,开始执行拥塞避免算法。并且新的ssthresh值是发生网络拥塞时窗口的 一半
-
拥塞避免算法:每次到达ssthresh值后,线性增加拥塞窗口
-
网络拥塞:发生拥塞后拥塞窗口马上降为初始值cwnd=1
一个传输轮次:
- 发送了一批报文段并收到它们的确认的时间
- 一个往返时延RTT
- 开始发送一批拥塞窗口内的报文段到开始发送下一批拥塞窗口内的报文段的时间
4)快重传和快恢复算法
快重传: 发送方收到 3个重复的冗余ACK ——>认为该报文段丢失,重传该报文段。在超时计时器之前执行快重传,可以实现快速重传报文段
快恢复:发生拥塞后不会像慢开始一样拥塞窗口降为初始值,而是 降到新的ssthresh值
拥塞避免:快恢复后继续执行拥塞避免,线性增加 拥塞窗口