Skip to content

运输层

作用

运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信。而网络层则是提供了主机之间逻辑通信。 因此运输层主要工作之一就是对报文进行端口的”封装“,而网络层是对ip地址的”封装“。

多路复用、多路分解

在接收端,运输层检查这些字段,标识出接收套接字,进而将报文段定向到该套接字。将运输层报文段中的数据交付到正确的套接字的工作称为多路分解。例如,网络请求中在接收端中解析出请求的端口号,然后找到对应的应用程序进行处理。

在源主机从不同套接字中收集数据块,并为每个数据块封装上首部信息从而生成报文段,然后将报文段传递到网络层,所有这些过程称为多路复用。多路复用需要封装源端口号字段目的端口号字段。端口号是一个16比特的数,在0~65535之间。0~1023范围的端口号称为周知端口号

无连接运输:UDP

UDP(用户数据报协议)为调用它的应用程序提供了一种不可靠无连接的服务。

UDP首部由4个字段组成,为8个字节:源端口号16比特,目的端口号16比特,检验和16比特, 报文长度16比特。

DNS是一个使用UDP的应用层协议的例子。

可靠数据传输原理

rdt1.0

假设底层信道是完全可靠的(实际上是TCP是在不可靠的IP网络层上实现的可靠的数据传输协议),那么接收端就不需要提供给发送端任何反馈信息。

rdt2.0

底层信道更为实际的模型是分组中的比特可能受损的模型。

  • 差错监测:判断分组是否受损
  • 接收方反馈:进行肯定确认(ACK)否定确认(NAK)
  • 重传:添加序号(seq),用于分辨分组并判断是否需要重传。

rdt3.0

  • 为了实现基于时间的重传机制,需要一个倒计时定时器,在一个给定时间量过期后,可中断发送方。
  • 停等协议(发送方等到ACK了才发送下一个请求)改为流水线的方式。解决流水线的差错恢复有两种方法:回退N步选择重传

滑动窗口结构

包含已被确认、已发送还未确认、可用但未发送和不可用四部分。

img

其中已发送还未确认可用但未发送的长度为窗口长度

回退N步

回退N步接收方丢弃所有失序分组,这种方法的优点是接收缓存简单,即接收方不需要缓存任何分组。

选择重传

接收方会缓存失序的分组,等到所有丢失的分组被收到的时候,这时才将一批分组按需交付给上层。

TCP

特点

  • 面向连接:传输数据前必须进行三次握手。
  • 可靠:保证数据的完整性。
  • 全双工服务:发送方和接收方可互相通信。

报文结构

首部一般是20字节:

  • 源端口号16比特
  • 目的端口号16比特
  • 序号32比特
  • 确认号32比特
  • 接收窗口16比特
  • 检验和16特比
  • 标志字段(FIN/SYN/ACK等等)和紧急数据指针共32比特

注意

  • TCP只确认该流中至第一个丢失字节为止的字节,所以TCP被称为累积确认

三次握手

img

  • 第一次:

    • SYN置为1,用于标识现在是握手。
    • 客户端随机选择一个初始序号seq为x。
    • 此时不包含应用层数据。
  • 第二次:服务端接收请求,为该TCP链接分配TCP缓存和变量。返回响应时:

    • 将SYN置为1,标识现在是握手。
    • 将客户端序号进行确认,返回ack为x+1。
    • 随机选择自己的初始序号,seq为y。
    • 此时不包含应用层数据。
  • 第三次:

    • 连接已经建立,SYN置为0。
    • 确认服务端的序号,ack为y+1。
    • 自身的序号seq为 x+1。
    • 携带应用层数据进行传输。

四次挥手

img

  • 第一次:客户端将FIN置为1,表示”我准备断开连接了“
  • 第二次:服务端接收到断开连接的报文,进行确认,表示”我已经知道你要断开连接了”。
  • 第三次:并等待一段时间,看下还有没有未处理的客户端的数据到来,如果没有的话,就开始告诉客户端“我也要断开连接了”。
  • 第四次:客户端接收到服务端的关闭请求,并进行确认,“你可以断开连接了”。并且客户端等待一段时间,用于确保服务端已经断开连接了。如果服务端没有正常断开连接,那么会进行重传。

SYN洪泛攻击

攻击者发送大量的TCP SYN报文段,而不完成第三次握手的步骤。随着SYN报文段的纷至沓来,服务器不断为这些半开连接分配资源(但从未使用),导致服务器的连接资源被消耗殆尽。

流量控制

服务端缓存已用空间可表示为:

服务端缓存已用空间 = 接收数据流的最后一个字节的编号 - 上层应用从缓存中读出的数据流的最后一个字节的编号

接收窗口rwnd可表示为:

rwnd = 服务器缓存总空间 - 服务器缓存已用空间

客户端接收到rwnd,需要保证:

最后发送的字节的编号 - 已经被确认的字节的编号 < rwnd

如果rwnd = 0,那么说明没有可用的空间了,此时客户端继续发送只有一个字节数据的报文段,直到服务端的rwnd > 0

拥塞控制

发送窗口 = min

  • 慢启动:拥塞窗口cwnd的值以1个MSS开始并且每当传输的报文段首次被确认就增加1个MSS。这个过程每过一个RTTcwnd就翻倍。因此是指数级增加,过程比较短。结束慢启动的方式有:

    • 接收到丢包事件时,将慢启动阈值(ssthresh)cwnd的一半,并将cwnd置为1,并重新开始慢启动过程。
    • 当达到或超过ssthresh时,结束慢启动转移到拥塞避免。
    • 如果检测到有3个冗余ACK,执行快速重传,进入快速恢复状态。
  • 拥塞避免:每一个新的确认到达cwnd加1。

    • 当出现超时时,与慢启动一样,ssthresh置为cwnd的一半, cwnd置为1。
    • 如果是接收到3个冗余ACKssthresh置为cwnd的一半, cwnd置为一半,进行快速恢复状态。
  • 快速恢复:对收到的每个冗余的ACKcwnd值增加一个MSS,当丢失报文的ACK都到达的时候,降低cwnd进入拥塞避免阶段。

    • 超时时,处理和慢启动一致。

差错校验

奇偶校验

附加一个比特,使得发送的信息的比特中1的个数为奇数(或偶数)。

为了更好的定位单个比特的出错信息,使用二维奇偶校验

校验和

d比特数据被作为一个k比特整数的序列处理。将所有k比特整数相加,加出来的值放到首部中(16比特)。接收方在接收数据的时候,做同样的处理,并与发送方的和进行相加取反。看最终相加的比特中是否包含0,如果包含,说明有比特出错。

循环冗余检测