套接字编程,如果我写入的数据超过一个 TCP/UDP 数据包可以携带会怎样?

Posted

技术标签:

【中文标题】套接字编程,如果我写入的数据超过一个 TCP/UDP 数据包可以携带会怎样?【英文标题】:socket programming, what happen if I write data more than one TCP/UDP packet can carry? 【发布时间】:2016-06-13 08:49:11 【问题描述】:

我有一个关于套接字编程的问题。当我使用 socket 发送数据时,我们可以使用 sendto() 等 API 使用 TCP 或 UDP 发送。 对于 sendto(),我们给出一个数组指针和我们要发送的字节数。

在这种情况下,如果我给出一个大字节数(例如:20000字节),根据我的理解,网络的MTU不会那么大,所以socket实际上发送多个数据包而不是一个大数据包。既然这 20000 字节被拆分成几个 UDP/TCP 数据包,那么这 20000 字节一开始会被视为一个数据包吗?这个过程是 UDP/TCP 碎片吗?

我的另一个问题是,如果我把小于MTU的数据放入sendto(),那么我可以保证调用一次sendto(),socket只发送一个TCP/UDP包?

提前致谢。

【问题讨论】:

UDP 不会按照您描述的方式对数据进行分段。 UDP 是一种面向消息的传输方式。您在 UDP 套接字上发送的内容将始终作为单个数据包发送,或者根本不发送数据包。另一方面,TCP 是一种面向流的传输方式,它会根据需要愉快地分解数据以适应网络缓冲区。 send()/sendto()的返回值会告诉你实际接受了多少字节进行传输,你要注意了。 【参考方案1】:

这 20000 字节一开始会被视为一个数据包吗?这个进程是 UDP/TCP 分片吗?

    如果您的套接字发送缓冲区足够大,UDP 会将其作为一个数据报发送。否则,您将获得 EMSGSIZE。它可能随后在 IP 层被分片,如果一个分片丢失,整个数据报也会丢失,但如果所有分片都到达,则整个数据报将被完整接收。

    TCP 将全部发送,按照它认为合适的方式对其进行分段和分段。除非网络中断时间足够长,否则一切都会完好无损地到达。

我的另一个问题是,如果我把小于MTU的数据放入sendto(),那么我可以保证调用一次sendto(),socket只发送一个TCP/UDP包?

    UDP:是的。 TCP:没有。

【讨论】:

TCP: 否 这是因为数据大小必须小于 MSS 而不是 MTU? @buddha 不,因为我上面说过:TCP 可以按照它喜欢的任何方式进行分段。 好吧,我对“TCP可以任意分段”的理解是,影响TCP分段的因素有很多,比如网络拥塞情况,而不仅仅是MSS。 我对“它喜欢的任何方式”的理解是“它喜欢的任何方式”。

以上是关于套接字编程,如果我写入的数据超过一个 TCP/UDP 数据包可以携带会怎样?的主要内容,如果未能解决你的问题,请参考以下文章

通过 C 中的套接字编程处理多个客户端

如果用户写入超过 1 列,如何从 Shiny 的数据框中选择列?

写入数据后向套接字发送错误响应

如何管理打开的数据报套接字以避免超过最大值?

ioctlsocket 或 recv 在 Windows 套接字编程中需要更多时间来执行?

如何使用套接字通道读取和写入数据并接受连接