2.11 缓冲区大小及限制

2.11 缓冲区大小及限制

下面我们将介绍一些影响IP数据报大小的限制。我们首先介绍这些限制,然后就它们如何影响应用进程能够传送的数据进行综合分析。

IPv4数据报的最大大小是65 535字节,包括IPv4首部。这是因为如图A-1所示其总长度字段占据16位。

IPv6数据报的最大大小是65 575字节,包括40字节的IPv6首部。这是因为如图A-2所示其净荷长度字段占据16位。注意,IPv6的净荷长度字段不包括IPv6首部,而IPv4的总长度字段包括IPv4首部。

IPv6有一个特大净荷(jumbo payload)选项,它把净荷长度字段扩展到32位,不过这个选项需要MTU(maximum transmission unit,最大传输单元)超过65 535的数据链路提供支持。(这是为主机到主机的内部连接而设计的,譬如HIPPI,它们通常没有内在的MTU。)

许多网络有一个可由硬件规定的MTU。举例来说,以太网的MTU是1500字节。另有一些链路(例如使用PPP协议的点到点链路)其MTU可以人为配置。较老的SLIP链路通常使用1006字节或296字节的MTU。

IPv4要求的最小链路MTU是68字节。这允许最大的IPv4首部(包括20字节的固定长度部分和最多40字节的选项部分)拼接最小的片段(IPv4首部中片段偏移字段以8个字节为单位)。IPv6要求的最小链路MTU为1280字节。IPv6可以运行在MTU小于此最小值的链路上,不过需要特定于链路的分片和重组功能,以使得这些链路看起来具有至少为1280字节的MTU(RFC 2460[Deering and Hinden 1998])。

在两个主机之间的路径中最小的MTU称为路径MTU(path MTU)。1500字节的以太网MTU是当今常见的路径MTU。两个主机之间相反的两个方向上路径MTU可以不一致,因为在因特网中路由选择往往是不对称的[Paxson 1196],也就是说从A到B的路径与从B到A的路径可以不相同。

当一个IP数据报将从某个接口送出时,如果它的大小超过相应链路的MTU,IPv4和IPv6都将执行分片(fragmentation)。这些片段在到达最终目的地之前通常不会被重组(reassembling)。IPv4主机对其产生的数据报执行分片,IPv4路由器则对其转发的数据报执行分片。然而IPv6只有主机对其产生的数据报执行分片,IPv6路由器不对其转发的数据报执行分片。

我们必须小心这些术语的使用。一个标记为IPv6路由器的设备可能执行分片,不过只是对于那些由它产生的数据报,而绝不是对于那些由它转发的数据报。当该设备产生IPv6数据报时,它实际上作为主机运作。举例来说,大多数路由器支持Telnet协议,管理员就用它来配置路由器。由路由器的Telnet服务器产生的IP数据报是由路由器产生的,而不是由路由器转发的。

你可能注意到,IPv4首部(图A-1)有用于处理IPv4分片的字段,IPv6首部(图A-2)却没有类似的字段。既然分片是例外情况而不是通常情况,IPv6于是引入一个可选首部以提供分片信息。

某些通常用作路由器的防火墙可能会重组分片了的分组,以便查看整个IP数据报的内容。这样做使得不必在防火墙上引入额外的复杂性就能够防止某些攻击。它还要求防火墙设备是进出网络的唯一路径上的设备,从而减少了冗余的机会。

IPv4首部(图A-1)的"不分片(don't fragment)"位(即DF位)若被设置,那么不管是发送这些数据报的主机还是转发它们的路由器,都不允许对它们分片。当路由器接收到一个超过其外出链路MTU大小且设置了DF位的IPv4数据报时,它将产生一个ICMPv4"destination unreachable, fragmentation needed but DF bit set"(目的地不可达,需分片但DF位已设置)出错消息(图A-15)。

既然IPv6路由器不执行分片,每个IPv6数据报于是隐含一个DF位。当IPv6路由器接收到一个超过其外出链路MTU大小的IPv6数据报时,它将产生一个ICMPv6"packet too big"(分组太大)出错消息(图A-16)。

IPv4的DF位和IPv6的隐含DF位可用于路径MTU发现(IPv4的情形见RFC 1191[Mogul and Deering 1990],IPv6的情形见RFC 1981[McCann, Deering, and Mogul 1996])。举例来说,如果基于IPv4的TCP使用该技术,那么它将在所发送的所有数据报中设置DF位。如果某个中间路由器返回一个ICMP"destination unreachable, fragmentation needed but DF bit set"错误,TCP就减小每个数据报的数据量并重传。路径MTU发现对于IPv4是可选的,然而IPv6的所有实现要么必须支持它,要么必须总是使用最小的MTU发送IPv6数据报。

路径MTU发现在如今的因特网上是有问题的,许多防火墙丢弃所有ICMP消息,包括用于路径MTU发现的上述消息。这意味着TCP永远得不到要求它降低所发送数据量的信号。编写本书时,IETF已经开始尝试定义不依赖于ICMP出错消息的另一种路径MTU发现方法。

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

TCP有一个MSS(maximum segment size,最大分节大小),用于向对端TCP通告对端在每个分节中能发送的最大TCP数据量。在图2-5中我们看到过SYN分节上的MSS选项。MSS的目的是告诉对端其重组缓冲区大小的实际值,从而试图避免分片。MSS经常设置成MTU减去IP和TCP首部的固定长度。在以太网中使用IPv4的MSS值为1460,使用IPv6的MSS值为1440(两者的TCP首部都是20个字节,但IPv4首部是20字节,IPv6首部却是40字节)。

在TCP的MSS选项中,MSS值是一个16位的字段,限定其最大值为65 535。这对于IPv4是适合的,因为IPv4数据报中的最大TCP数据量为65 495(65 535减去IPv4首部的20字节和TCP首部的20字节)。然而对于具有特大净荷选项的IPv6,却需要使用另外一种技巧(RFC 2675[Borman, Deering, and Hinden 1999])。首先,没有特大净荷选项的IPv6数据报中的最大TCP数据量为65 515(65 535减去TCP首部的20字节)。65 535这个MSS值于是被视为表示"无限"的一个特殊值。该值只在用到特大净荷选项时才使用,不过这种情况却要求实际的MTU超过65 535。其次,如果TCP使用特大净荷选项,并且接收到的对端通告的MSS为65 535,那么它所发送数据报的大小限制就是接口MTU。如果这个值太大(也就是说所在路径中某个链路的MTU比较小),那么路径MTU发现功能将确定这个较小值。

SCTP基于到对端所有地址发现的最小路径MTU保持一个分片点。这个最小MTU大小用于把较大的用户消息分割成较小的能够以单个IP数据报发送的若干片段。SCTP_MAXSEG套接字选项可以影响该值,使得用户能够请求一个更小的分片点。

2.11.1 TCP输出

2.11.1 TCP输出

图2-15展示了某个应用进程写数据到一个TCP套接字中时发生的步骤。

每一个TCP套接字有一个发送缓冲区,我们可以使用SO_SNDBUF套接字选项来更改该缓冲区的大小(见7.5节)。当某个应用进程调用write时,内核从该应用进程的缓冲区中复制所有数据到所写套接字的发送缓冲区。如果该套接字的发送缓冲区容不下该应用进程的所有数据(或是应用进程的缓冲区大于套接字的发送缓冲区,或是套接字的发送缓冲区中已有其他数据),该应用进程将被投入睡眠。这里假设该套接字是阻塞的,它是通常的默认设置。(我们将在第16章中阐述非阻塞的套接字。)内核将不从write系统调用返回,直到应用进程缓冲区中的所有数据都复制到套接字发送缓冲区。因此,从写一个TCP套接字的write调用成功返回仅仅表示我们可以重新使用原来的应用进程缓冲区,并不表明对端的TCP或应用进程已接收到数据。(我们将在7.5节随SO_LINGER套接字选项详细讨论这一点。)

 
(点击查看大图)图2-15 应用进程写TCP套接字时涉及的步骤和缓冲区

这一端的TCP提取套接字发送缓冲区中的数据并把它发送给对端TCP,其过程基于TCP数据传送的所有规则(TCPv1的第19章和第20章)。对端TCP必须确认收到的数据,伴随来自对端的ACK的不断到达,本端TCP至此才能从套接字发送缓冲区中丢弃已确认的数据。TCP必须为已发送的数据保留一个副本,直到它被对端确认为止。

本端TCP以MSS大小的或更小的块把数据传递给IP,同时给每个数据块安上一个TCP首部以构成TCP分节,其中MSS或是由对端通告的值,或是536(若对端未发送一个MSS选项)。(536是IPv4最小重组缓冲区字节数576减去IPv4首部字节数20和TCP首部字节数20的结果。)IP给每个TCP分节安上一个IP首部以构成IP数据报,并按照其目的IP地址查找路由表项以确定外出接口,然后把数据报传递给相应的数据链路。IP可能在把数据报传递给数据链路之前将其分片,不过我们已经谈到MSS选项的目的之一就是试图避免分片,较新的实现还使用了路径MTU发现功能。每个数据链路都有一个输出队列,如果该队列已满,那么新到的分组将被丢弃,并沿协议栈向上返回一个错误:从数据链路到IP,再从IP到TCP。TCP将注意到这个错误,并在以后某个时刻重传相应的分节。应用进程并不知道这种暂时的情况。

2.11.2 UDP输出

2.11.2 UDP输出

图2-16展示了某个应用进程写数据到一个UDP套接字中时发生的步骤。

这一次我们以虚线框展示套接字发送缓冲区,因为它实际上并不存在。任何UDP套接字都有发送缓冲区大小(我们可以使用SO_SNDBUF套接字选项更改它,见7.5节),不过它仅仅是可写到该套接字的UDP数据报的大小上限。如果一个应用进程写一个大于套接字发送缓冲区大小的数据报,内核将返回该进程一个EMSGSIZE错误。既然UDP是不可靠的,它不必保存应用进程数据的一个副本,因此无需一个真正的发送缓冲区。(应用进程的数据在沿协议栈向下传递时,通常被复制到某种格式的一个内核缓冲区中,然而当该数据被发送之后,这个副本就被数据链路层丢弃了。)

 
图2-16 应用进程写UDP套接字时涉及的步骤与缓冲区

这一端的UDP简单地给来自用户的数据报安上它的8字节的首部以构成UDP数据报,然后传递给IP。IPv4或IPv6给UDP数据报安上相应的IP首部以构成IP数据报,执行路由操作确定外出接口,然后或者直接把数据报加入数据链路层输出队列(如果适合于MTU),或者分片后再把每个片段加入数据链路层的输出队列。如果某个UDP应用进程发送大数据报(譬如说2000字节的数据报),那么它们相比TCP应用数据更有可能被分片,因为TCP会把应用数据划分成MSS大小的块,而UDP却没有对等的手段。

从写一个UDP套接字的write调用成功返回表示所写的数据报或其所有片段已被加入数据链路层的输出队列。如果该队列没有足够的空间存放该数据报或它的某个片段,内核通常会返回一个ENOBUFS错误给它的应用进程。

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

TCP/IP知识理解(下)相关推荐

  1. 以太网数据帧的报尾封装字段是什么_利用TCP/IP模型理解数据通信过程

    回顾TCP/IP模型 TCP/IP模型是当今IP网络的基础(由OSI七层参考模型发展而来,也称为DoD模型). 分层参考模型的设计是非常经典的理念: 层次化的模型设计将网络的通信过程划分为更小.更简单 ...

  2. HTTP—TCP/IP—SOCKET理解及浅析

    一个完整的HTTP请求的过程 此举例为抛砖引玉,引导大家进入思考状态. 当你按输入www.baidu.com ,浏览器接收到这个消息之后,浏览器根据自己的算法识别出你要访问的URL,为您展示出来搜索页 ...

  3. socket,TCP/IP的理解(转)

    TCP/IP 要想理解socket首先得熟悉一下TCP/IP协议族, TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间 ...

  4. c++tcp接收文件缓存多大合适_必知必会的TCP/IP知识

    点击上方「蓝字」关注我们 1 TCP/IP模型 TCP/IP协议模型(Transmission Control Protocol/Internet Protocol),包含了一系列构成互联网基础的网络 ...

  5. 一篇文章带你详解 TCP/IP 协议(下)

    前面的第一二三章已在上篇讲解,还没看过的可以先看看:一篇文章带你详解 TCP/IP 协议(上) 本文继续讲解第四章. 四.网络层中的 IP 协议 IP(IPv4.IPv6)相当于 OSI 参考模型中的 ...

  6. TCP/IP 协议理解

    TCP/IP 协议(Transmission Control Protocol / internet Protocol),因特网互联协议,又名网络通讯协议.通俗而言:TCP负责发现传输的问题,一有问题 ...

  7. 面试100题:TCP/IP的理解

    三次握手: TCP/IP协议是一个传输层面向连接的安全可靠的传输协议,三次握手是为了建立一个安全可靠的连接.第一次握手是从客户端发起向服务端发送一个报文,报文将SYN位标志位置为1.当服务端收到了就知 ...

  8. linux tcp ip c,Linux下TCP/IP编程--TCP实战(select)

    本文参考自徐晓鑫<后台开发>,记录之. 一.为什么要使用非阻塞I/O之select 初学socket的人可能不爱用select写程序,而习惯诸如connect.accept.recv/re ...

  9. TCP/IP知识总结面试题之Socket服务

    1.如何新建一个客户端Socket服务 //new出一个对象即可 //指定链接的IP地址,端口号 Socket socket =new Socket("www.baidu.com" ...

最新文章

  1. 大数据教程(13.6)sqoop使用教程
  2. Android 项目,没有可运行的Module项
  3. 操作系统(八)进程状态的转换以及进程组织方式
  4. boost::stacktrace模块实现终止处理程序的测试程序
  5. 查看vsftpd内容为空,不能建立文件夹
  6. linux下的字符设备驱动
  7. Common Sort - 排序 - Java
  8. C/C++之大端小端
  9. DBX到PDF转换器
  10. atomic与nonatomic的区别
  11. Android 监听短信2种方式:Broadcast和ContentObserver
  12. 音视频编辑软件哪个好
  13. vue tab页面缓存处理
  14. html5+css3实现2D动画效果演示
  15. R语言 sub()用法
  16. Wordpress网页直接插入bilibili视频方法
  17. 新装固态硬盘SSD,在安装WIN10,显示一直请稍后及Windows安装程序无法将Windows配置为此计算机的解决方法(网上都是胡诌)
  18. 驱动开发入门:WDK与VS2010
  19. postgresql获取当前或某一时间段的年月日
  20. 计算机考试电脑故障考官说没事,山东春季高考潍坊一考点计算机故障 官方启动调查...

热门文章

  1. 春季出游季,名悦集团分享那些常见的高速公路危险驾驶
  2. DASCTFBJDCTF 3rd 部分writeup
  3. SharePoint 教程
  4. 面向工业园区的5G垂直组网类服务探讨
  5. 机器学习-对数几率回归(逻辑回归)算法
  6. 女人怎么去爱自己的男人!!(给女士们看看)声明我是男的 ^_^
  7. LaTeX之罗列多个公式
  8. kotlin新建项目的报错和自定义kotlin中的loge的live template
  9. 拓商:如何投资才能把店铺做起来
  10. c# FTP服务器文件上传下载等操作