【计算机网络】传输层
2021-05-04 10:06:43 #计算机网络 

传输层

概述

传输层使用网络层的服务,为应用层提供通信服务

只有主机才有的层次

功能:

  1. 传输层提供进程和进程之间的逻辑通信
  2. 复用和分用

    复用:应用层所有的应用进程都可以通过传输层再传输到网络层

    分用:传输层从网络层收到数据后交付指明的应用进程

    现有设备 A 和 B,都分别运行一个网页,一个 QQ,这两种程序的协议不同,设备 A 的两个进程都发送信息给设备 B。设备 A 的传输层根据协议的不同,对两组信息分别添加标识符,然后将两组信息打包传递给网络层发出去,这是复用;设备 B 的传输层从网络层接收到打包来的数据后,根据协议识别标识符,把给 QQ 的信息传送给 QQ,给网页的信息传送给网页,这是分用

  3. 对收到的报文进行差错检测
  4. 两种协议

    TCP:面向连接的传输控制协议

    可靠,面向连接,时延大,适用于大文件


    UDP:无连接的用户数据报协议

    不可靠,无连接,时延小,适用于小文件


寻址与端口

通过端口号标识主机中的应用进程

端口号长度为 16bit,能标识 个不同的端口号

image-20210504131437664

image-20210504131458676

套接字:唯一标识网络中的一个主机和它的一个进程

套接字 Socket = (主机 IP 地址,端口号)


UDP 协议

概述

UDP 只在 IP 数据报服务上增加少量功能,即复用分用和差错检测功能

特点:

  1. UDP 是无连接的,减少开销和发送数据之前的时延
  2. UDP 使用最大努力交付,即不保证可靠交付
  3. UDP 是面向报文的,适合一次性传输少量数据的网络应用

    面向报文:完全接收应用层传输下来的完整报文,并封装传递到网络层,不会切割

  4. UDP 无拥塞控制,适合很多实时应用

    例如对实时性要求较高的视频聊天等

  5. UDP 首部开销小

    UDP 首部大小:8B

    TCP 首部大小:20B


首部格式

image-20210504133416289

源端口号:可有可无,不需要目标回话时可以不写(全 0)

UDP 长度:首部字段长度 + 数据字段长度

UDP 检验和:检测 UDP 数据报是否出错,错误则丢弃


UDP 校验

image-20210504133735066

伪首部:只有在计算检验和时才出现,不向下传送也不向上递交

①:固定为 0

②:封装 UDP 报文的 IP 数据报首部协议字段是 17

UDP 长度:UDP 首部 8B + 数据部分长度(不包括伪首部)

image-20210504134407447

在发送端:

  1. 填上伪首部
  2. 全 0 填充检验和字段
  3. 全 0 填充数据部分(UDP 数据报要看成许多 4B 的字串接起来)
  4. 伪首部 + 首部 + 数据部分采用二进制反码求和
  5. 把和求反码填入检验和字段
  6. 去掉伪首部,发送

在接收端:

  1. 填上伪首部
  2. 伪首部 + 首部 + 数据部分采用二进制反码求和
  3. 结果全为 1 则无差错,否则丢弃数据报/交给应用层附上出差错的警告

TCP 协议

特点

  1. 面向连接的传输层协议

    传输数据前先接通连接,建立连接后传输数据,传输结束销毁连接

  2. 每条 TCP 连接只有两个端点,处于应用程序之间(端口),即每条 TCP 连接时是端对端的(不是点对点)

    TCP 连接是端对端连接是怎么回事呢?TCP 连接相信大家都很熟悉,但是 TCP 连接是端对端连接是怎么回事呢,下面就让博主带大家一起了解吧。
    TCP 连接是端对端连接,其实就是 TCP 连接是端对端连接,不是点对点连接。大家可能会很惊讶 TCP 连接怎么会是端对端连接呢?但事实就是这样,博主也感到非常惊讶。
    这就是关于 TCP 连接是端对端连接的事情了,大家有什么想法呢,欢迎在评论区告诉博主一起讨论哦!

  3. TCP 提供可靠交付的服务,无差错、不丢失、不重复、按序到达

  4. TCP 提供全双工通信

    设置发送缓存和接收缓存

    发送缓存:准备发送的数据 & 已发送但尚未收到确认的数据

    接收缓存:按序到达但尚未被接受应用程序读取的数据 & 不按序到达的数据

  5. TCP 面向字节流

    流:流入到进程或从进程流出的字节序列

    TCP 把应用程序交下来的数据看成仅仅是一连串的无结构的字节流


TCP 报文段首部格式

image-20210504142239952

序列号:在一个 TCP 连接中传送的字节流中的每一个字节都按顺序编号,本字段表示本报文段所发送数据的第一个字节的序列号

确认号:期望收到对方下一个报文段的第一个数据字节的序列号。

若确认号为 N,则证明到序号 N-1 为止的所有数据都已正确收到,期望下一个收到的报文段的序号为 N

例题:

主机甲与主机乙之间建立 TCP 连接,主机甲向乙发送了一个序号为 100 的报文段,包含 200 字节的有效载荷,主机乙正确接收到这个报文段后,发送给主机甲的确认号为(300

分析:当主机乙收到从序号 100 开始的 200 字节的有效载荷,最后一个字节序号应当是 299,确认号需要 +1,即发送确认号 300 给主机甲

数据偏移(首部长度):TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远,以 4B 位单位,即 1 个数值是 4B

首部中可能存在其他选项,导致首部长度不明,因此通过数据偏移,计算 TCP 数据部分在整个 TCP 报文段中的起始位置

6 个控制位:

紧急位URGURG=1时,标明此报文段中有紧急数据,是高优先级的数据,应尽快传送,不用在缓存里排队,配合紧急指针字段使用

确认位ACKACK=1时确认号有效,在连接建立后所有传送的报文段都必须把 ACK 置为 1

推送位PSHPSH=1时,接收方尽快交付接收应用进程,不再等到缓存填满再向上交付

复位RSTRST=1时,表明 TCP 连接中出现严重差错,必须释放连接,然后再重新建立传输链接

同步位SYNSYN=1时,表明是一个连接请求/接受报文

终止位FINFIN=1时, 表明此报文段发送方数据已发完,要求释放连接

窗口:指的是发送本报文段的一方的接收窗口,即现在允许对方发送的数据量

接收方向发送方发送的报文段中,利用窗口指明接收方可以容纳的数据量,用来限制发送方的发送缓存大小

16bit 位,表示最大为 大小

例:

接收方报文段的确认号设置为 701,窗口设置为 1000

则发送方发出的报文段的字节序列号应当为从 701 到 1700

检验和:检验首部 + 数据,检验时要加上 12B 大小的伪首部,第四个字段为 6

紧急指针:URG=1时才有意义,指出本报文段中紧急数据的字节数

从 TCP 数据报部分开头到指明的字节数长度的数据,作为紧急数据

选项:最大报文段长度 MSS、窗口扩大、时间戳、选择确……


TCP 连接管理(三次握手与四次挥手)

建立方式:客户服务器方式(C/S),主动发起连接建立的应用进程是客户,被动等待连接建立的应用进程是服务器

连接建立的三个阶段(三次握手)

image-20210504145118292

  1. 客户端发送连接请求报文段(SYN),无应用层数据

    SYN=1,seq=x(随机)

    设置同步位SYN为 1,表明这是一个连接请求报文

    seq(序列号)生成一个随机值client_isn,记为 x

    发送前客户端处于CLOSED状态;发送后处于SYN_SENT,并等待服务端返回的 SYNACK

  2. 服务端为该 TCP 连接分配缓存和变量,并向客户端返回确认报文段(SYNACK),允许连接,无应用层数据

    SYN=1,ACK=1,seq=y(随机),ack=x+1

    确认报文段,则同步位SYN设置为 1

    确认位ACK设置为 1,表明确认号有效

    seq(序列号)生成一个随机值server_isn,记为 y

    确认号ack根据连接请求报文段中的序列号,+1,表示期望收到的下一个字节序列号

    服务器应用程序创建监听套接字,从CLOSED状态转变为LISTEN状态

    当处于LISTEN状态并接收到 SYN 后,转变为SYN_RCVD状态,并返回 SYNACK

  3. 客户端为该 TCP 连接分配缓存和变量,并向服务端返回确认报文段的确认(ACK),可以携带数据

    SYN=0,ACK=1,seq=x+1,ack=y+1

    开始正常传输数据,同步位SYN设置为 0

    确认位ACK设置为 1,表明确认号有效

    收到 SYNACK 前客户端处于SYN_SENT状态;收到后处于ESTABLISHED状态,此时客户端可以接收和发送包含有效载荷数据的 TCP 报文

    服务端收到 ACK 后由SYN_RCVD状态转变为ESTABLISHED状态,等待客户端的正常请求并返回相应资源


SYN 洪泛攻击:客户端(攻击者)向服务器发送大量连接请求报文,接收到服务器的确认报文段后不进行确认,此时 TCP 连接处于挂起状态(半连接状态,服务器分配了缓存和变量);服务器接收不到确认,会重复发送 ACK 给攻击者,浪费服务器资源;大量的连接请求报文和恶意攻击,导致无法完成每一个三次握手,消耗服务器内存和 CPU,可能导致服务器死机

如何解决?

SYN cookie,如同浏览器的 cookie,服务器在接收到连接请求报文时,利用报文内的源和目的 IP 地址、端口号以及服务器自有的特殊值,通过特殊的复杂函数生成一个 cookie,并附加在连接确认报文中作为server_isn发送回去,此时没有为这个 TCP 连接分配资源,也不会记录这个 cookie

如果客户端正常返回确认报文段,服务器端通过确认报文段中的源和目的 IP 地址、端口号以及服务器自有的特殊值,再次计算 cookie。此时报文段中的确认号应当是 cookie+1


连接释放的四个阶段(四次握手)

参与一条 TCP 连接的两个进程中的任何一个进程都可以终止该连接,释放缓存和变量

image-20210504151220254

  1. 客户端发送连接释放报文段(FIN),停止发送数据,主动关闭 TCP 连接

    FIN=1,seq=u

    设置终止位FIN为 1,表明此报文段发送方数据已发完,要求释放连接

    序列号根据上一个报文段确定取值

    发送 FIN 后客户端处于FIN_WAIT_1状态

  2. 服务端返回一个确认报文段(ACK),客户端—服务器端这个方向的连接释放,处于半关闭状态

    ACK=1,seq=v,ack=u+1

    服务端接收到 FIN 后由ESTABLISHED状态转变为CLOSE_WAIT状态

    客户端收到 ACK 后处于FIN_WAIT_2状态,等待服务端主动发送的连接释放报文段

  3. 服务端发完数据,发出连接释放报文段(FIN),主动关闭 TCP 连接

    FIN=1,ACK=1,seq=w,ack=u+1

    设置终止位FIN为 1,表明此报文段发送方数据已发完,要求释放连接

    ack=u+1:第二步服务端发送报文段后,客户端并没有回发报文段,所以第二步和第三步服务端发送的报文段的ack都设置为 u+1

    服务端发送 FIN,由CLOSE_WAIT状态转变为LAST_ACK状态

  4. 客户端回送一个确认报文段(ACK),再等到时间等待计数器设置的2MSL(最长报文段寿命)后,连接彻底关闭

    ACK=1,seq=u+1,ack=w+1

    客户端收到 FIN 后,发送 ACK,在时间等待计数器设置的时间内处于TIME_WAIT状态,经过等待后正式关闭

    服务端接收到 ACK 后,由LAST_ACK状态转变为CLOSED状态

    当服务端没有接收到确认报文段时,会重发一个连接释放报文段,客户端在2MSL的时间中会接收到连接释放报文段后重发确认报文段


网络编程—C/S 模型

image-20210715201311482

服务器:

1.socket(),创建 socket,获得文件描述符
2.bind(),绑定 socket 到服务器(本地 IP)对外暴露的端口
3.listen(),对 socket 设置定长的监听队列,开始监听
4.accept(),从监听队列中选取一个远端 socket(IP 和端口),建立连接
5.fork(),分配逻辑处理单元,处理客户请求,监听 socket 继续监听
6.recv(),逻辑处理单元接收客户端请求
7.send(),发送客户端请求的数据
8.recv(),接收客户端关闭通知,当业务处理完毕,调用close()关闭服务器—> 客户端连接(TCP 四次挥手)

客户端:

1.socket(),创建 socket,获得文件描述符
2.connect(),由 socket 连接到服务器(IP 地址)的特定端口,双方进行 TCP 三次握手(及 HTTPS 的 TLS/SSL 四次握手)
3.send(),通过 socket 向服务器发送请求
4.recv(),接收服务器数据
5.close(),关闭客户端—> 服务器连接(TCP 四次挥手)


TCP 可靠传输

网络层提供尽最大努力交付,不可靠传输;传输层使用 TCP 实现可靠传输(UDP 不可靠,需要应用层实现可靠传输)

可靠传输:保证接收方进程从缓存区读出的字节流与发送方发出的字节流是完全一样的

  1. 校验:增加伪首部检验
  2. 序号:一个字节占一个序号
    序号字段:一个报文段的第一个字节的序号
  3. 确认:接收方发送确认报文段,指导发送方接下来应该发送的数据

    例:

    发送方 TCP 缓存:有十个字节,序号从 1 到 10,先发送序号从 1 到 3 的字节;发送后缓存中不删除 1 到 3 号字节

    接收方 TCP 缓存:接收从 1 到 3 号的字节,存入缓存

    接收方向发送方发送确认报文段,首部中确认号为 4,表示希望发送方接下来发送以以序号 4 的字节开头的数据

    发送方接收到确认报文段,确认 1 到 3 号正常接收,删除缓存中的 1 到 3 号;并根据要求发送 4 到 6 号,和 7 到 8 号

    接收方未接收到 4 号开头的数据,但是接收到了 7 号开头的数据;此时默认使用累计确认,返回确认报文段,确认号仍然为 4,指导接收方重传 4 开头的数据

  4. 重传:发送方在规定时间(重传时间)内没有收到确认就重传已发送的报文段(超时重传

    重传时间:自适应算法,计算 RTTs(加权平均往返时间)

    根据每次发送报文段和接收确认报文段的往返时间,加权计算,动态改变重传时间


TCP 流量控制

流量控制:让发送方慢点,让接收方来得及接收

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

在通信过程中,接收方根据自己接收缓存的大小动态地调整发送方的发送窗口大小,即接收窗口 rwnd(接收方设置确认报文段的窗口字段来将 rwnd 通知给发送方),发送方的发送窗口取接收窗口 rwnd 和拥塞口 cwnd 的最小值

接收方可以设置窗口为 0,此时发送方不能发送数据,接收方可以处理数据;接收方处理后再发送一个报文段,重新设置窗口大小,发送方根据窗口大小继续发送数据

A 向 B 发送数据,连接建立时,B 告诉 A:『 我的 rwnd=400 (字节)』,设每一个报文段 100B,报文段序号初始值为 1

image-20210504161014457

接收方设置窗口为 0,重新发送报文段设置窗口时,报文段可能丢失,导致发送方窗口一直为 0,接收方一直等着发送方的报文,形成『死锁』

TCP 为每一个连接设有一个持续计时器,只要 TCP 连接的一方收到对方的零窗口通知,就启动持续计时器

若持续计时器设置的时间到期,就发送一个零窗口探测报文段。接收方收到探测报文段时给出现在的窗口值

若窗口仍然是 0,那么发送方就重新设置持续计时器


TCP 拥塞控制

拥塞条件:对资源需求的总和 > 可用资源

拥塞控制:防止过多的数据注入到网络中

假定:

  1. 数据单方向传送,而另一个方向只传送确认
  2. 接收方总是有足够大的缓存空间,因而发送窗口大小取决于拥塞程度

发送窗口 = Min { 接收窗口 rwnd,拥塞窗口 cwnd }

接收窗口:接收方根据接受缓存设置的值,并告知给发送方,反映接收方容量

拥塞窗口:发送方根据自己估算的网络拥塞程度而设置的窗口值,反映网络当前容量


慢开始和拥塞避免

image-20210504162613561

一个传输轮次:

发送了一批报文段并收到它们的确认的时间

一个往返时延 RTT

开始发送一批拥塞窗口内的报文段到开始发送下一批拥塞窗口内的报文段的时间


快重传和快恢复

image-20210504163033905