【问题标题】:C++ Socket Buffer SizeC++ 套接字缓冲区大小
【发布时间】:2016-09-29 09:10:18
【问题描述】:

这更像是一个确认请求而不是一个问题,所以我会保持简短。 (我离开了我的电脑,所以不能简单地实现这个解决方案来测试)。

我正在编写一个程序,将通过网络摄像头拍摄的图像文件(连同元数据)从树莓派发送到我的电脑。

我计算出图像大约为 130kb,数据包标头为 12b,相关元数据为 24b。虽然将来我可能会增加图像大小,但一旦我有一个工作原型。

目前我无法成功检索整个数据包,因为在将其发送到 PC 后,我只能在缓冲区中收到大约 64kb 的数据。

我假设这是因为无论出于何种原因,套接字的默认缓冲区大小声明如下:

SOCKET sock = socket(PF_INET, SOCK_STREAM, 0);

是 64kb(如果您“知情”,请有人澄清一下)

所以 - 为了解决这个问题,我打算通过 setsockopt(x..) 命令将套接字大小增加到 1024kb。

请有人确认我对问题的诊断和建议的解决方案是否正确?

我问这个问题是因为我现在不在我的电脑上,在我回家之前无法尝试。

【问题讨论】:

  • 我在精神上为自己准备的另一种选择是手动分割数据包。但是,我怀疑这会引入更多的错误可能性,并且会增加整体数据包大小/计算时间,因为我需要为每个单独的段发送和读取标头。
  • 你没有收到所有数据的原因是你假设recv() 填充了你的缓冲区而不是循环。文档中没有任何内容支持该假设。
  • 感谢您的回复,不是 100% 肯定我会关注您,但要澄清一下:我知道传入数据的大小,因为它存储在标题中,并且被提取、读取和适当大小分配缓冲区以接收其余数据。因此,进一步说明: >获取具有数据包大小的标头 >创建正确大小的缓冲区 >运行 recv 以填充缓冲区并记下接收到的字节 >检查接收到的字节与标头中的数据大小

标签: c++ sockets buffer setsockopt


【解决方案1】:

这很可能与套接字缓冲区无关,但事实上recv() 和send() 不必接收和发送您想要的所有数据。检查这些函数调用的返回值,它表明实际发送和接收了多少字节。

处理“短”读/写的最佳方法是将它们放在一个循环中,如下所示:

char *buf;  // pointer to your data
size_t len; // length of your data
int fd;     // the socket filedescriptor

size_t offset = 0;
ssize_t result;
while (offset < len) {
  result = send(fd, buf + offset, len - offset, 0);
  if (result < 0) {
     // Deal with errors here
  }
  offset += result;
}

使用类似的结构来接收数据。请注意,一种可能的错误情况是函数调用被中断(errno = EAGAIN 或EWOULDBLOCK),在这种情况下,您应该重试发送命令,在所有其他情况下,您应该退出循环。

【讨论】:

  • 感谢@G.Sliepen。所以,我看到你正在循环发送,因此建议(如果不是,请纠正我)在接收端,应该使用循环接收。 -- 什么是防止接收非预期数据的保护,例如从无关程序发送到端口的附带数据包?我能想到的唯一方法是在其中放置一个带有“第 10 部分,共 20 部分”类型 ID 的标题。这似乎不会造成更多问题吗? -- 我想我的主要问题是我可以不只是增加发送/接收使用的内部系统缓冲区的大小吗?即setsockopt...
  • 是的,您应该在接收端使用接收循环​​。 TCP 套接字(我假设您正在使用它)始终从单个连接提供有序的数据流。因此,您不会从不相关的网络连接中收到虚假数据,并且您会看到所有数据都按照发送时的顺序进入。
猜你喜欢
  • 1970-01-01
  • 2011-11-15
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-16
相关资源
最近更新 更多