会员登录 | 注册

来去留技术信息资源

来去留技术信息资源
来去留网 > 流行服务 > 网络应用 > 来看TCP分包粘包MTU和MSS之间的关系分析

来看TCP分包粘包MTU和MSS之间的关系分析

2015-01-09 21:55来源:未知发布者:laiquliu 查看:

       IP分片在以太网上,由于电气限制,一帧不能超过1518字节,除去以太网帧头14字节(mac地址等)和帧尾4字节校验,还剩1500字节,这个大小称 为MTU(最大传输单元)。如果你的IP包大于1500字节,IP层就会分片了。而1492的MTU值的来源,是因为PPPoE协议。PPP协议是宽带运 营商用于对用户认证计费的(TCP/IP以太网无此功能)。PPPoE头尾一共8字节,所以有效载荷MTU变小了,原来有1500字节,现在只剩1492 了。这1492还包含20字节IP头,8字节UDP头或者20字节TCP头。所以真正的不分片数据,UDP为1492-28=1464,TCP为 1492-40=1452字节。TCP的确是流的,所以TCP一个包可以包含的数据大小为65536(包头长度定义为2字节).a向b连续发送数据,b在 每次接受到数据大小大于其低水位后,你的recv就会返回(假设是阻塞模式),并得到数据长度。当然你要持续接受和处理数据。如果实际数据大于1452字 节,IP会分片,但IP也会重组分片,所以还是一次recv就可以收到(不一定全,但跟分片无关)。如果一个分片丢失,则整个TCP包都会重发,因为IP 层不会将没收完的分片交给传输层。ACK确认的时机,是收到了就会确认上一次的完整包的TCP序列号,如果不完整当然要等收完整,也不会交互到应用层,也 不会发送ACK确认(可以通过3次确认上一个完整的序列号以让发送方快传)。握手协商和ACKTCP在发起3次握手时,会协商MSS(最大分节大小),这 个值一般是路径最小MTU-IP头-TCP头,如果MTU是1500,则1500-20-20=1460字节。这样,每个包就不用IP层再分片了。所以你 发2000字节,你调用一次send,如果发送缓冲区移动窗口够大,应该会全部成功。否则,会返回实际发送的字节。假设2000字节全部成功,tcp实际 会将其分为1460和540两个包发送,接受端接受到1460这个包就会回一次ACK,接到540大小这个再ACK一次。每个分节都带有IP头和TCP头 的。IP分片只有第一个带有传输层头,其余的分片只有IP头。

从上面的文章中可以看到,MTU是硬件设施决定的,然后由这个值推断出数据包的大小,在以太网上,最大分节MSS为1460。

UDP和TCP协议利用端口号实现多项应用同时发送和接收数据。数据通过源端口发送出去,通过目标端口接收。有的网络应用只能使用预留或注册的静态端口; 而另外一些网络应用则可以使用未被注册的动态端口。因为UDP和TCP报头使用两个字节存放端口号,所以端口号的有效范围是从0到65535。动态端口的 范围是从1024到65535。  

MTU最大传输单元,这个最大传输单元实际上和链路层协议有着密切的关系,EthernetII帧的结构DMAC+SMAC+Type+Data+CRC 由于以太网传输电气方面的限制,每个以太网帧都有最小的大小64bytes最大不能超过1518bytes,对于小于或者大于这个限制的以太网帧我们都可 以视之为错误的数据帧,一般的以太网转发设备会丢弃这些数据帧。

由于以太网EthernetII最大的数据帧是1518Bytes这样,刨去以太网帧的帧头(DMAC目的MAC地址48bit=6Bytes+SMAC 源MAC地址48bit=6Bytes+Type域2bytes)14Bytes和帧尾CRC校验部分4Bytes那么剩下承载上层协议的地方也就是 Data域最大就只能有1500Bytes这个值我们就把它称之为MTU。

UDP 包的大小就应该是 1500 – IP头(20) – UDP头(8) = 1472(BYTES)
TCP 包的大小就应该是 1500 – IP头(20) – TCP头(20) = 1460 (BYTES)

注*PPPoE所谓PPPoE就是在以太网上面跑“PPP”。随着宽带接入(这种宽带接入一般为Cable Modem或者xDSL或者以太网的接入),因为以太网缺乏认证计费机制而传统运营商是通过PPP协议来对拨号等接入服务进行认证计费的,所以引入 PPPoE。PPPoE导致MTU变小了以太网的MTU是1500,再减去PPP的包头包尾的开销(8Bytes),就变成1492。不过目前大多数的路 由设备的MTU都为1500。

如果我们定义的TCP和UDP包没有超过范围,那么我们的包在IP层就不用分包了,这样传输过程中就避免了在IP层组包发生的错误;如果超过范围,既IP 数据报大于1500字节,发送方IP层就需要将数据包分成若干片,而接收方IP层就需要进行数据报的重组。更严重的是,如果使用UDP协议,当IP层组包 发生错误,那么包就会被丢弃。接收方无法重组数据报,将导致丢弃整个IP数据报。UDP不保证可靠传输;但是TCP发生组包错误时,该包会被重传,保证可 靠传输。

UDP数据报的长度是指包括报头和数据部分在内的总字节数,其中报头长度固定,数据部分可变。数据报的最大长度根据操作环境的不同而各异。从理论上说,包含报头在内的数据报的最大长度为65535字节(64K)。

我们在用Socket编程时, UDP协议要求包小于64K,TCP没有限定。

不过鉴于Internet上的标准MTU值为576字节,所以建议在进行Internet的UDP编程时,最好将UDP的数据长度控制在548字节 (576-8-20)以内。

就具体函数而言:

用UDP协议发送时,用sendto函数最大能发送数据的长度为:65535- IP头(20) – UDP头(8)=65507字节。用sendto函数发送数据时,如果发送数据长度大于该值,则函数会返回错误。

用TCP协议发送时,由于TCP是数据流协议,因此不存在包大小的限制(暂不考虑缓冲区的大小),这是指在用send函数时,数据长度参数不受限制。而实 际上,所指定的这段数据并不一定会一次性发送出去,如果这段数据比较长,会被分段发送,如果比较短,可能会等待和下一次数据一起发送。

(责任编辑:laiquliu)

关注技术,信息,资源,扫描来去留网微信二维码交流。

来去留我李俊

搜索

------分隔线----------------------------
相关栏目

热点推荐
来去留技术信息资源
来去留网为您提供平台咨询交流学习方法及各类热门技术;电器,服装,保健,行业快讯等二十几个类别的资讯