【问题标题】:Why do a socket reads more data than what is actually sent?为什么套接字读取的数据比实际发送的数据多?
【发布时间】:2013-09-19 09:29:06
【问题描述】:

我有一个用 C 语言编写并在 Linux 上运行的客户端和服务器。客户端请求数据段并将相似的数据段发送到服务器。以下是客户端和服务器之间的典型交互。

  1. 客户端告诉服务器保存一些数据(即写请求)。该请求由 4KB 的数据和几个额外的元数据字节组成(2xunsigned long + 1xint)。服务器保存数据并且不响应写入请求。
  2. 客户端向服务器请求数据(即读取请求)。该请求由几个字节的元数据组成(再次... 2xunsigned long + 1xint)。服务器只响应一个 4KB 的数据段。

服务器端的跟踪显示它总是发送 4KB 的数据段。但是,客户端的跟踪显示了一个不同的故事:不同大小的数据包。如果客户端在某一时刻接收到大小不是 4KB 的数据,则以下数据包加起来是 4KB 或 8KB。

为了说明错误的模式,这里有一些我在跟踪中看到的示例:

  • 4KB,1200 字节,2896 字节,4KB。
  • 4KB,1448 字节,6744 字节,4KB。

我可能可以通过等待读取完整的 4KB 段来处理应用程序级别的第一种情况(即 1200B+2896B),但我不知道如何处理其他情况。但是,我宁愿完全避免整个问题,并强制客户端/服务器接收每个 4KB 的完整数据段。

我已经尝试禁用 Nagle 算法 (TCP_NODELAY) 并将 MTU 大小设置为 4KB。但是没有一个能解决这个问题。

【问题讨论】:

  • 不要试图强制 readwrite 处理 4KB 块,你会失败。而是像处理流一样处理网络;只有当您有 4KB 数据(+元数据)可用时,您才能从您的套接字中持续读取和缓冲并进行处理。
  • 如何测量数据包大小?可能是您在不同的层进行测量(即 TCP 层在一个,应用层在另一个)?这将导致如此不同的数字。
  • 你能看出1448+6744==8192==2*4096不是巧合吗?那么,那么:继续阅读直到你有你的障碍。然后回来阅读更多当你准备好了。 (这就是@MichaelFoukarakis 所说的,顺便说一句)

标签: c linux sockets tcp


【解决方案1】:

为什么套接字读取的数据比实际发送的数据多?

它没有。它会读取任何可用的数据,如果没有,则在必要时阻塞。

您的问题是建立在一个谬误之上的。 TCP 协议规范或伯克利套接字 API 中的任何地方都不能保证一次读取 == 一次写入。 TCP 是一种字节流协议。如果到达的数据多于您的预期,并且您提供给 recv() 或 read() 方法的缓冲区中有足够的空间,您将得到它。如果您想要消息边界,则完全由您来实现它们。

【讨论】:

  • 好吧,好吧...我在凌晨 4 点写了问题描述...难怪标题搞砸了。无论如何,看起来所有 cmets 之间都有一个协议,这不能完成,我必须在从套接字读取时处理它。谢谢大家!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 2020-09-16
  • 2012-06-04
相关资源
最近更新 更多