android 分包粘包_关于TCP封包、粘包、半包

本文深入探讨TCP的分包与粘包现象,解释了TCP如何通过超时重传策略保证传输可靠性,并分析了Windows TCP栈中200ms延迟确认、Nagle算法以及Winsock缓冲对小数据包传输的影响。通过案例分析,提出了优化小数据包传输性能的建议,包括数据拼接、设置TCP_NODELAY和适当调整缓冲区大小等方法。
摘要由CSDN通过智能技术生成

关于Tcp封包

很多朋友已经对此作了不少研究,也花费不少心血编写了实现代码和blog文档。当然也充斥着一些各式的评论,自己看了一下,总结一些心得。

首先我们学习一下这些朋友的心得,他们是:

//………………

当然还有太多,很多东西粘来粘区也不知道到底是谁的原作,J

看这些朋友的blog是我建议亲自看一下TCP-IP详解卷1中的相关内容【原理性的内容一定要看】。

TCP大致工作原理介绍:

工作原理

TCP-IP详解卷1第17章中17.2节对TCP服务原理作了一个简明介绍(以下蓝色字体摘自《TCP-IP详解卷1第17章17.2节》):

尽管T C P和U D P都使用相同的网络层(I P),T C P却向应用层提供与U D P完全不同的服务。T C P提供一种面向连接的、可靠的字节流服务。

面向连接意味着两个使用T C P的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个T C P连接。这一过程与打电话很相似,先拨号振铃,等待对方摘机说“喂”,然后才说明是谁。在第1 8章我们将看到一个T C P连接是如何建立的,以及当一方通信结束后如何断开连接。

在一个T C P连接中,仅有两方进行彼此通信。在第1 2章介绍的广播和多播不能用于T C P。

T C P通过下列方式来提供可靠性:

•应用数据被分割成T C P认为最适合发送的数据块。这和U D P完全不同,应用程序产生的数据报长度将保持不变。由T C P传递给I P的信息单位称为报文段或段(s e g m e n t)(参见图1 - 7)。在1 8 . 4节我们将看到T C P如何确定报文段的长度。

•当T C P发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。在第2 1章我们将了解T C P协议中自适应的超时及重传策略。

•当T C P收到发自T C P连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒,这将在1 9 . 3节讨论。

• T C P将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,T C P将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发)。

•既然T C P报文段作为I P数据报来传输,而I P数据报的到达可能会失序,因此T C P报文段的到达也可能会失序。如果必要,T C P将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。

•既然I P数据报会发生重复,T C P的接收端必须丢弃重复的数据。

• T C P还能提供流量控制。T C P连接的每一方都有固定大小的缓冲空间。T C P的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。两个应用程序通过T C P连接交换8 bit字节构成的字节流。T C P不在字节流中插入记录标识符。我们将这称为字节流服务(byte stream service)。如果一方的应用程序先传1 0字节,又传2 0字节,再传5 0字节,连接的另一方将无法了解发方每次发送了多少字节。收方可以分4次接收这8 0个字节,每次接收2 0字节。一端将字节流放到T C P连接上,同样的字节流将出现在T C P连接的另一端。另外,T C P对字节流的内容不作任何解释。T C P不知道传输的数据字节流是二进制数据,还是A S C I I字符、E B C D I C字符或者其他类型数据。对字节流的解释由T C P连接双方的应用层解释。这种对字节流的处理方式与U n i x操作系统对文件的处理方式很相似。U n i x的内核对一个应用读或写的内容不作任何解释,而是交给应用程序处理。对U n i x的内核来说,它无法区分一个二进制文件与一个文本文件。

T C P如何确定报文段的长度

我仍然引用官方解释《TCP-IP详解卷1》第18章18.4节:

最大报文段长度(M S S)表示T C P传往另一端的最大块数据的长度。当一个连接建立时【三次握手】,连接的双方都要通告各自的M S S。我们已经见过M S S都是1 0 2 4。这导致I P数据报通常是4 0字节长:2 0字节的T C P首部和2 0字节的I P首部。

在有些书中,将它看作可“协商”选项。它并不是任何条件下都可协商。当建立一个连

接时,每一方都有用于通告它期望接收的M S S选项(M S S选项只能出现在S Y N报文段中)。如果一方不接收来自另一方的M S S值,则M S S就定为默认值5 3 6字节(这个默认值允许2 0字节的I P首部和2 0字节的T C P首部以适合5 7 6字节I P数据报)。

一般说来,如果没有分段发生,M S S还是越大越好(这也并不总是正确,参见图2 4 - 3和图2 4 - 4中的例子)。报文段越大允许每个报文段传送的数据就越多,相对I P和T C P首部有更高的网络利用率。当T C P发送一个S Y N时,或者是因为一个本地应用进程想发起一个连接,或者是因为另一端的主机收到了一个连接请求,它能将M S S值设置为外出接口上的M T U长度减去固定的I P首部和T C P首部长度。对于一个以太网,M S S值可达1 4 6 0字节。使用IEEE 802.3的封装(参见2 . 2节),它的M S S可达1 4 5 2字节。

如果目的I P地址为“非本地的( n o n l o c a l )”,M S S通常的默认值为5 3 6。而区分地址是本地还是非本地是简单的,如果目的I P地址的网络号与子网号都和我们的相同,则是本地的;如果目的I P地址的网络号与我们的完全不同,则是非本地的;如果目的I P地址的网络号与我们的相同而子网号与我们的不同,则可能是本地的,也可能是非本地的。大多数T C P实现版都提供了一个配置选项(附录E和图E - 1),让系统管理员说明不同的子网是属于本地还是非本地。这个选项的设置将确定M S S可以选择尽可能的大(达到外出接口的M T U长度)或是默认值5 3 6。

M S S让主机限制另一端发送数据报的长度。加上主机也能控制它发送数据报的长度,这将使以较小M T U连接到一个网络上的主机避免分段。

只有当一端的主机以小于5 7 6字节的M T U直接连接到一个网络中,避免这种分段才会有效。

如果两端的主机都连接到以太网上,都采用5 3 6的M S S,但中间网络采用2 9 6的M T U,也将会

出现分段。使用路径上的M T U发现机制(参见2 4 . 2节)是关于这个问题的唯一方法。

以上说明MSS的值可以通过协商解决,这个协商过程会涉及MTU的值的大小,前面说了:【MSS=外出接口上的MTU-IP首部-TCP首部】,我们来看看数据进入TCP协议栈的封装过程:

6db3ea6e6d8acbdace2d586407ce835c.png

最后一层以太网帧的大小应该就是我们的出口MTU大小了。当目的主机收到一个以太网数据帧时,数据就开始从协议栈中由底向上升,同时去掉各层协议加上的报文首部。每层协议盒都要去检查报文首部中的协议标识,以确定接收数据的上层协议。这个过程称作分用(D e m u l t i p l e x i n g),图1 - 8显示了该过程是如何发生的。

a73a89e6c975809e0e19db7b9fbe6df4.png

那么什么是MTU呢,这实际上是数据链路层的一个概念,以太网和802.3这两种局域网技术标准都对“链路层”的数据帧有大小限制:

833c05fd9d7df63401e440a19279a061.png

l最大传输单元MTU

正如在图2 - 1看到的那样,以太网和8 0 2 . 3对数据帧的长度都有一个限制,其最大值分别是1 5 0 0和1 4 9 2字节。链路层的这个特性称作M T U,最大传输单元。不同类型的网络大多数都有一个上限。

如果I P层有一个数据报要传,而且数据的长度比链路层的M T U还大,那么I P层就需要进行分片(f r a g m e n t a t i o n),把数据报分成若干片,这样每一片都小于M T U。我们将在11 . 5节讨论I P分片的过程。

图2 - 5列出了一些典型的M T U值,它们摘自RFC 1191[Mogul and Deering 1990]。点到点的链路层(如S L I P和P P P)的M T U并非指的是网络媒体的物理特性。相反,它是一个逻辑限制,目的是为交互使用提供足够快的响应时间。在2 . 1 0节中,我们将看到这个限制值是如何计算出来的。在3 . 9节中,我们将用n e t s t a t命令打印出网络接口的M T U。

l路径MTU

当在同一个网络上的两台主机互相进行通信时,该网络的M T U是非常重要的。但是如果

两台主机之间的通信要通过多个网络,那么每个网络的链路层就可能有不同的M T U。重要的

不是两台主机所在网络的M T U的值,重要的是两台通信主机路径中的最小M

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值