(5) 缓冲区大小及限制

一、简述说明

本章主要理解一些影响IP数据报大小的限制因素,及就这些因素是如何影响应用进程能够传送的数据进行综合分析理解。

1.1 数据报大小
  • IPv4数据报的最大大小是65535字节,包括IPv4首部。这是因为表示总长度的字段在IPv4首部中占据16位,总长度包括IPv4首部,如图1所示:
    在这里插入图片描述
图1 IPv4首部格式
  • IPv6数据报的最大大小是65575字节,包括40字节的IPv6首部。这是因为如图2所示其净荷长度字段占据16位。其净荷长度不包括IPv6首部。
    在这里插入图片描述
图2 IPv6首部格式
  • 许多网络有一个可由硬件规定的MTU。比如,以太网的MTU是1500字节。IPv4要求的最小链路MTU是68字节。IPv6要求的最小链路MTU为1280字节。
  • 在两个主机之间的路径中最小的MTU称为路径MTU(path MTU)。1500字节的以太网MTU是当今常见的路径MTU。两个主机之间相反的两个方向上路径MTU可以不一致,因为在因特网中路由选择往往是不对称的。
  • 当一个IP数据报将从某个接口送出时,如果它的大小超过相应链路的MTU,IPv4和IPv6都将执行分片(fragmentation)。这些片段在到达最终目的地之前通常不会被重组(reassembling)。IPv4主机对其产生的数据报执行分片,IPv4路由器则对其转发的数据报执行分片。然而IPv6只有主机对其产生的数据报执行分片,IPv6路由器不对其转发的数据报执行分片。
1.2 不分片与DF位

IPv4不分片:

  1. 图1中的IPv4首部的“不分片(don‘t fragment)”位(即DF位)若被设置,那么不管是发送这些数据报的主机还是转发他们的路由器,都不允许对他们分片。
  2. 当路由器接收到一个超过其外出链路MTU大小且设置了DF位的IPv4数据报时,它将产生一个ICMPv4错误,如下所示:
# 错误信息
ICMPv4 “destination unreachable,fragmentation needed but DF bit set”
# 翻译后内容
目的地不可达,需分片但DF已设置

IPv6不分片:

  1. 既然IPv6路由器不执行分片,每个IPv6数据报于是隐含一个DF位
  2. 当IPv6路由器接收到一个超过其外出链路MTU大小的IPv6数据报时,它将产生一个ICMPv6错误信息,如下所示:
# 错误信息
ICMPv6 “packet too big”
# 译文
分组太大

DF位:

  1. IPv4的DF位和IPv6的隐含DF位可用于路径MTU发现,详细如下:

    IPv4的情形见RFC 1991 [Mogul and Deering 1990]

    IPv6的情形见RFC 1981 [McCann,Deering,and Mogul 1996]

  2. 假设,如果基于IPv4的TCP使用路径MTU发现该技术,那么它将在所发送的所有数据报中设置DF位。如果某个中间路由器返回一个ICMPv4 “destination unreachable,fragmentation needed but DF bit set”错误,TCP就减少每个数据报的数据量并重传

  3. 路径MTU发现对于IPv4是可选的,然而IPv6的所有实现要么必须支持它,要么必须总是使用最小的MTU发送IPv6数据报

1.3 最小重组缓冲区与MSS

最小重组缓冲区大小:

  1. IPv4和IPv6都定义了最小重组缓冲区大小(minimum reassembly buffer size),它是IPv4或IPv6的任何实现都必须保证支持的最小数据报大小。
  2. 最小重组缓冲区大小的值对于IPv4为576字节,对于IPv6为1500字节。例如,就IPv4而言,很多时候不能判断某个给定目的地能否接受577字节的数据报,为此许多使用UDP的IPv4网络应用(如DNS、RIP、TFTP、BOOTP、SNMP)避免产生大于这个大小的数据报。

TCP的MSS:

  1. TCP有一个MSS(maximum segment size,最大分节大小),用于向对端TCP通告对端在每个分节中能发送的最大TCP数据量。

  2. MSS的目的是告诉对端其重组缓冲区大小的实际值,从而试图避免分片。

  3. MSS经常设置成MTU减去IP和TCP首部的固定长度。在以太网中使用IPv4的MSS值为1460,使用IPv6的MSS值为1440(IPv4与IPv6的TCP首部都是20字节,但IPv4的首部是20字节,IPv6的首部却是40字节)。

  4. 在TCP的MSS选项中,MSS值是一个16位的字段,限定器最大值为65535。

    # MSS值对于IPv4
    对于IPv4是合适的,因为IPv4数据报中的最大TCP数据量为65495(65535减去IPv4首部的20字节和TCP首部的20字节)
    # MSS值对于IPv6
    对于具有特大净荷选项的IPv6,却需要使用另外一种规则,依赖于RFC 2675 [Borman,Deering,and Hinden 1999]:
    (1) 首先,没有特大净荷选项的IPv6数据报中的最大TCP数据量为65515(65535减去TCP首部的20字节)。
    (2) 其次,如果TCP使用特大净荷选项,并且接收到的对端通告的MSS为65535,那么它所发送数据报的大小限制就是接口MTU。如果这个值太大(也就是说所在路径中某个链路的MTU比较小),那么路径MTU发现功能将确定这个较小值。
    

二、TCP输出

图3展示了某个应用进程写数据到一个TCP套接字中时发生的步骤。如下所示:
在这里插入图片描述

图3 应用进程写TCP套接字时涉及的步骤和缓冲区
2.1 图3说明

每一个TCP套接字有一个发送缓冲区,可以使用SO_SNDBUF套接字选项来更改该缓冲区的大小

从用户进程缓冲区到套接字发送缓冲区过程说明:

(1) 当某个应用进程调用write时,内核从该应用进程的缓冲区中复制所有数据到所写套接字的发送缓冲区中。

(2) 如果该套接字的发送缓冲区容不下该应用进程的所有数据(或者说应用进程的缓冲区大于套接字的发送缓冲区,或者是套接字的发送缓冲区中已有其它数据),该应用进程将被投入睡眠

(3) 接(2)小节描述,假设该套接字是阻塞的,当然阻塞方式也是通常的默认设置。内核将不从write系统调用返回,直到应用进程缓冲区中的所有数据都复制到套接字发送缓冲区。

(4) 因此,从TCP套接字的write调用成功返回仅仅表示可以重新使用原来的应用进程缓冲区,并不表明对端的TCP或应用进程已接收到数据。

(5) 发送端的TCP提取套接字发送缓冲区中的数据并把它发送给对端TCP,其过程基于TCP数据传送的所有规则。

(6) 对端TCP必须确认收到的数据,伴随来自对端的ACK的不断到达,本端TCP至此才能从套接字发送缓冲区中丢弃已确认的数据。TCP必须为已发送的数据保留一个副本,直到它被对端确认为止。

本端TCP发送数据时的封装及传递过程:

(1) 本端TCP以MSS大小的或更小的块把数据传递给IP,同时给每个数据块安上一个TCP首部以构成TCP分节, 其中MSS或是由对端通告的值,或是536(若对端未发送一个MSS选项,536是IPv4最小重组缓冲区字节数576减去IPv4首部字节数20和TCP首部字节数20的结果)。

(2) IP给每个TCP分节安上一个IP首部以构成IP数据报,并按照其目的IP地址查找路由表已确定外出接口,然后把数据包传递给响应的数据链路。

(3) IP可能在把数据报传递给数据链路之前将其分片,不过前面谈到MSS选项的目的之一就是试图避免分片.

(4) 每个数据链路都有一个输出队列,如果该队列已满,那么新到的分组将被丢弃,并沿协议栈向上返回一个错误:

  • 从数据链路到IP,再从IP到TCP。
  • TCP将注意到这个错误,并在以后的某个时刻重传相应的分节。应用进程并不知道这种暂时的情况。

三、UDP输出

图4展示了某个应用进程写数据到一个UDP套接字中时发生的步骤,如下所示:
在这里插入图片描述

图4 应用进程写UDP套接字时涉及的步骤与缓冲区
3.1 图4说明

图4以虚线框展示套接字发送缓冲区,因为它实际上并不存在。

任何UDP套接字都有发送缓冲区大小,可以使用SO_SNDBUF套接字选项更改它,不过它仅仅是可写到该套接字的UDP数据报的大小上限

从用户进程缓冲区到套接字发送缓冲区过程说明:

(1) 当一个应用进程写一个大于套接字发送缓冲区大小的数据报,内核将返回该进程一个EMSGSIZE错误。

(2) 既然UDP是不可靠的,它不必保存应用进程数据的一个副本,因此无需一个真正的发送缓冲区

(3) 无需副本详细说明: 应用进程的数据在沿协议栈向下传递时,通常被复制到某种格式的一个内核缓冲区中,然而当该数据被发送之后,这个副本就被数据链路层丢弃了。

本段UDP发送数据时的封装及传递过程:

(1) 本端UDP简单的给来自用户应用进程的数据报添加上8字节的首部以构成UDP数据报

(2) IPv4或IPv6给UDP数据报安上相应的IP首部以构成IP数据报

(3) 执行路由操作确定外出接口,或者直接把数据报加入数据链路层输出队列(如果适合于MTU),或者分片后再把每个片段加入数据链路层的输出队列。

(4) 如果某个UDP应用进程发送大数据报(比如发送2000字节的数据报),相比于TCP应用数据更有可能被分片,因为TCP会把应用数据划分成MSS大小的块,而UDP却没有对等的手段。

(5) 从写一个UDP套接字的write调用成功返回表示所写的数据报或其所有片段已被加入数据链路层的输出队列

(6) 如果该输出队列没有足够的空间存放该数据报或它的某个片段,内核通常会返回一个ENOBUFS错误给它的应用进程

注意: 不幸的是,有些UDP的实现不返回ENOBUFS错误,这样甚至数据报未经发送就被丢弃的情况应用进程也不知道。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值