TCP和UDP数据包可以分成几块吗?

TCP数据包可以通过分段到达接收器吗?

例如,如果我使用TCP协议发送20个字节,我可以100%确定我将一次接收20个字节,而不是10个字节,然后是另外10个字节左右?

和UDP协议相同的问题。
我知道UDP是不可靠的,数据包根本不能到达或按不同的顺序到达,但是单个数据包呢? 如果到达,我可以确定它是一个完整的数据包,而不是一个?

TCP数据包可以通过分段到达接收器吗?

是。 IP支持分段,尽pipeTCP通常试图确定pathMTU并保持其数据包小于性能原因。 碎片增加灾难性的数据报丢失率。 如果path的丢包率为10%,则将数据报分成两个数据包会使数据报损失率接近20%。 (如果两个数据包丢失,数据报丢失。)

你不必担心这个,TCP层也没有。 IP层将数据包重新组装成整个数据报。

例如:如果我使用TCP协议发送20个字节,我可以100%确定我会一次接收20个字节,而不是10个字节,然后是另外10个字节左右?

不,但这与数据包无关。 TCP从根本上说是一种不保存应用程序消息边界的字节stream协议。

和UDP协议相同的问题。 我知道UDP是不可靠的,数据包根本不能到达或按不同的顺序到达,

TCP也是如此。 数据包是数据包。 不同之处在于TCP具有重试和重新sorting,而UDP则不是。

但是1包呢? 如果到达,我可以确定它是一个完整的数据包,而不是一个?

不,但那不是你的问题。 UDP协议处理数据报重组。 这是其工作的一部分。 (实际上,IP协议对于UDP协议是这样做的,所以UDP只是通过在IP之上进行分层来实现的。)如果一个数据报被分成两个分组,那么IP协议将会重新组装UDP协议,所以你将看到完整的数据。

你不能确定他们真的一次到达。 TCP / UDP下面的数据链接层可能会将数据包分开。 特别是如果你通过互联网或任何你不能控制的networking发送数据,很难预测这一点。

但是无论数据是在一个数据包中还是在接收器中多个数据包到达。 操作系统应该抽象这些数据包的连接,所以对于你的应用程序来说,它看起来就像是一切都到达了。 所以,除非你是内核黑客,否则在大多数情况下,你不必担心这个数据是以一个还是多个数据包传输的。

对于UDP,操作系统也会做一些抽象,所以接收数据的应用程序不必知道数据已经传输了多less包。 但与TCP的不同之处在于数据实际到达不能保证。 数据也可能分成多个数据包,其中一些到达,另一些则不到。 对于接收应用程序来说,它看起来就像是一个数据stream,不pipe它是否完整。

例子。 连续字符块对应于send()调用:

TCP:

Send: AA BBBB CCC DDDDDD E Recv: A ABB B BCC CDDD DDDE 

所有发送的数据都按顺序接收,但不一定在同一个块中。

UDP:

 Send: AA BBBB CCC DDDDDD E Recv: CCC AA E 

数据不一定按照相同的顺序,并且不一定完全接收,但是消息被全部保存。

例如:如果我使用TCP协议发送20个字节,我可以100%确定我会一次接收20个字节,而不是10个字节,然后是另外10个字节左右?

不,TCP是一个stream协议,它保持数据的顺序,但不按消息分组。 另一方面,UDP是面向消息的,但不可靠。 SCTP具有两全其美的优点,但由于NAT打破了互联网,因此不能在本地使用。

有一些保证,如果你在一个TCPstream的最开始发送20个字节,它不会以两个10字节块到达。 这是因为TCP堆栈不会发送这样的小段:有一个最小的MTU大小。 但是,如果发送是在一个stream中的任何地方,所有的投注都closures。 可能是你的协议栈需要10个字节的数据来填充一个段并将其发送出去,然后接下来的十个字节到另一个段。

您的协议栈将数据分成块,并将它们放入队列中。 块大小基于pathMTU。 如果你执行一个发送操作,并且还有排队的数据挂起,那么协议栈通常会查看队列尾部的段,并查看该段是否有空间来添加更多的数据。 房间可能只有一个字节,所以即使是两个字节的发送也可以分成两个字节。

另一方面,数据的分割意味着可以有部分读取。 接收操作可能会在只有一个段到达时唤醒并获取数据。 在广泛使用的套接字API中,接收调用可以要求20个字节,但可以返回10个。当然,可以在其上build立一个缓冲层,这个缓冲层将会阻塞,直到接收到20个字节,或者连接中断。 在POSIX的世界里,这个API可以是标准的I / Ostream:你可以fdopen一个套接字描述符来获得一个FILE *stream,并且你可以用fread来填充一个缓冲区,这样完整的请求就可以满足read电话。

UDP数据报构成数据。 每个发送调用都会生成一个数据报(但请参阅下面有关软木塞)。 另一端接收一个完整的数据报(并且在套接字API中,它必须指定一个足够大的缓冲区来存放它,否则数据报将被截断)。 大数据报被IP分片碎片化,并且被透明地重新组合到应用程序中。 如果任何片断丢失,整个数据报丢失; 在这种情况下无法读取部分数据。

存在对接口的扩展,允许多个操作指定单个数据报。 在Linux中,套接字可以被“软木塞”(阻止发送)。 书写的数据被塞入一个单元。 然后,当套接字被“拔出”时,可以发送一个数据报。