我们知道,当应用层程序之间进行网络数据传输时,在发送端,数据会从应用层沿着协议栈向下传输,通过TCP/IP层,然后经由链路层发送出去,而在接收端,则是相反的顺序,数据经由链路层接收,然后沿着协议栈向上传输,通过IP/TCP层,最后由应用层程序进行读取。
而在IP层往链路层传输数据的时候,往往会做一个分片的操作,对于大多数链路层来讲,它都有一个最大传输单元(MTU),表示能够发送数据量的大小,它是由硬件决定的。比如以太网的MTU为1500字节。当IP层传输给链路层的数据量大于其MTU时,那么IP层就会将数据拆分为小于其链路层MTU的数据片,再传输给链路层进行发送。
但是对于不同的传输层协议(TCP/UDP)来说,在IP层上,需不需要进行分片是不同的。
TCP层的分片
对于TCP来说,它是尽量避免分片的,为什么?因为如果在IP层进行分片了话,如果其中的某片的数据丢失了,对于保证可靠性的TCP协议来说,会增大重传数据包的机率,而且只能重传整个TCP分组(进行IP分片前的数据包),因为TCP层是不知道IP层进行分片的细节的,也不关心。
当TCP层进行TCP分组的重传后,还会直接影响到应用层程序的性能,特别是在应用程序使用阻塞IO进行读写的时候。要理解这点,首先我们要知道当应用层程序往TCPIP协议栈写数据的时候都做了些什么事。
在应用层程序中,我们可以有自己的发送缓冲区,而TCP层本身也有自己的一个发送缓冲区,在JAVA中,可以通过设置Socket的SO_SNDBUF选项来设置,默认情况下一般是8k大小。 当我们在应用层往TCP层写数据(比如outputstream.write())的时候,实际上是将应用层发送缓冲区的数据拷贝到TCP层的发送缓冲区中。当TCP层的发送缓冲区满或者网络空闲时,TCP层就会将其缓冲区中的数据通过IP层传到链路层的发送队列中。如果TCP层的发送缓冲区满而且应用层的数据没有写完时,内核会将write系统调用挂起,并不返回给应用层程序,直到应用层的数据全部拷贝到TCP层的缓冲区中。而由于TCP层要保证数据包的可靠性,即数据包丢失时要进行重传,那么TCP层在往网络发送TCP分组后,需要在其发送缓冲区中暂时保存发出的TCP分组数据用于后续可能的重传。
在这样的前提下,如果IP对来自TCP层的数据进行了分片, 那么就有可能使得应用层程序一直在write系统调用处挂起等待,引起性能的下降。
TCP层如何避免IP层的分片
首先,我们先回顾下TCP建立连接的3次握手:
在这3次握手中,除了确认SYN分节外,通信的两端还进行协商了一个值,MSS,这个值用来告诉对方,能够发送的TCP分节的大小。这个值一般是取其链路层的MTU大小减去TCP头部大小和IP头部的大小。MSS=MTU-TCP头部大小-IP头部大小.
MTU的值可以通过询问链路层得知。
当两端确认好MSS后进行通信,当TCP层往IP层传输数据时,如果TCP层缓冲区的大小大于MSS,那么TCP层都会将其发送缓冲区中的数据切分成MSS大小的分组进行传输,由于MSS是通过MTU减去TCP头部大小和IP头部的大小计算得出的,MSS肯定比MTU小,那么到IP层的时候就可以避免IP层的分片。
UDP层的分片
如果我们采用的是UDP协议而不是TCP协议呢?在IP层会不会进行分片?由于UDP是不需要保证可靠性的,那么它就不会保存发送的数据包,TCP之所以保存发送的数据包是因为要进行重传。所以UDP本身是没有像TCP一样的发送缓冲区的。这就导致了对UDP进行write系统调用的时候,实际上应用层的数据是直接传输到IP层,由于IP层本身也不会有缓冲区,数据就会直接写到链路层的输出队列中。
在这种情况下,IP层会不会对来自UDP的数据进行分片呢?这个取决于UDP数据报的大小。如果UDP数据报的大小大于链路层的MTU,那么IP层就会直接进行分片,然后在发送到链路层的输出队列中,反之,则不会进行分片,直接加上IP头部发送到链路层的输出队列中。
TCP/UDP实验
看完了理论,让我们实践一把,看是否与以上的理论相符。
对于TCP来说,它是尽量避免分片的。假设我们这里要发送给TCP层的数据大小为2748个字节,这个大小是明显大于链路层的发送数据的大小的,在这个情况下我们来看,对于来自TCP层的数据,IP会不会进行分片。
从第一张图看来,应用层的2748个字节在TCP层就进行了分段,分层了两个TCP段,一个1460字节,一个1288字节。那么到IP层的时候,自然就不会在进行分片了。
从第二张图片看出,在这两个TCP分段中,在序号3处,IP的头部字段(Don ' t Fragment)
被设置了,用于告诉IP层不要对该数据进行分片。
而对于MSS大小的协商,我们可以从下面这张图片看到,下面的图片是TCP CLIENT发出的第一个SYN TCP分段:
对于UDP来说,假设我们要发送的一个UDP数据包大小为1600个字节,那么在实际上通过UDP/IP分发出去的时候,会不会进行分片呢? 看如下的图片:
从上面的图片可以看出,我们发送的数据包的大小为1600字节(序号1处),在UDP层,长度为1608字节(序号2处),这里的8个字节是UDP的头部字段的长度, 到了IP层(序号3处),我们可以清楚的看到IP对UDP数据包进行了分片,一个大小为1480字节,一个为128字节。
- 大小: 4 KB
- 大小: 14.1 KB
- 大小: 11.6 KB
- 大小: 81.2 KB
- 大小: 37.4 KB
- 大小: 92.1 KB
- 大小: 31.5 KB
分享到:
相关推荐
TCPIP-232
《基于UCOS的TCP/IP协议栈开发详解》 在嵌入式系统开发中,网络通信功能的实现至关重要,而Micrium的uC/TCP-IP是广泛应用的一种嵌入式TCP/IP协议栈。本文将深入探讨如何在UCOS操作系统环境下,利用uC/TCP-IP进行...
《TCP/IP详解卷》是一本深入探讨网络协议的权威书籍,尤其关注TCP/IP协议栈的核心组件。这本书由W. Richard Stevens、Stephen A. Thomas和Karl A. Prosser共同编写,提供了对TCP/IP协议族的全面理解。高清PDF版本...
备份标志指示是否应将选项复制到每个分片的IP头部。 9.3.4 选项列表给出了RFC 791定义的IP选项,包括选项常量、十进制和二进制值,以及它们的长度。Net/3实现了一些选项,例如选项表的结束(EOI)、无操作(NOP)、...
TCPIP协议族-第4版.z01
tcpip-and-the-as400.tgz
MODBUS--TCPIP协议--介绍.doc
11.5 IP分片 111 11.6 ICMP不可达差错(需要分片) 113 11.7 用Traceroute确定路径MTU 114 11.8 采用UDP的路径MTU发现 116 11.9 UDP和ARP之间的交互作用 118 11.10 最大UDP数据报长度 119 11.11 ICMP源站抑制差错 ...
本书内容十分丰富,几乎涵盖了有关TCP/IP的各个方面,包括开放式通信模型、TCP/IP通信模型、IP网络中的命名和寻址机制、地址解析及反向地址解析协议、DNS域字服务器、WINS、地址发现协议、IPv6、IP网络中的路由协议...
追踪Linux TCPIP代码运行--基于2.6内核,附带目录索引
追踪Linux TCPIP代码运行--基于2.6内核.pdf
追踪Linux TCPIP代码运行--基于2.6内核.pdf
WinCC-TCP/IP-S7-200Smart 通信教程 WinCC7.5 是一种工业自动化软件,西门子 S7-200Smart PLC 是一种高性能的程序逻辑控制器。为了实现 WinCC 与 S7-200Smart PLC 之间的通信,需要通过 TCP/IP 协议建立连接。下面...
在复习TCP/IP时,理解各层之间的交互和协议功能是基础,同时需要掌握如TCP的流量控制、拥塞控制、IP分片与重组、子网划分与子网掩码计算等高级主题。对于研究生课程,可能还会涉及到更深入的内容,如QoS(服务质量)...
追踪Linux TCPIP代码运行-基于2.6内核.pdf
还有个 TCPIP协议族-第4版.z01