首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在套接字库中调用recv时,recv缓冲区应该有多大

在套接字库中调用recv时,recv缓冲区应该有多大
EN

Stack Overflow用户
提问于 2010-05-19 08:19:47
回答 6查看 118.5K关注 0票数 145

关于C中的套接字库,我有几个问题。下面是我将在问题中引用的代码片段。

代码语言:javascript
复制
char recv_buffer[3000];
recv(socket, recv_buffer, 3000, 0);

  1. 我如何决定recv_buffer的规模有多大?我使用的是3000,但这是任意的。
  2. 如果recv()收到的数据包比我的缓冲区大会发生什么?
  3. 我怎么知道我已经收到了整个消息,而不需要再次调用recv,并让它在没有接收到任何东西的情况下一直等待?
  4. 有没有一种方法可以让一个缓冲区没有固定的空间,这样我就可以继续添加它,而不用担心空间耗尽?
  5. 也许可以使用strcat将最新的recv()响应连接到缓冲区?

我知道这其中有很多问题,但如果有任何回应,我会非常感激。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-05-19 08:53:16

这些问题的答案取决于您使用的是流套接字(SOCK_STREAM)还是数据报套接字(SOCK_DGRAM) -在TCP/IP中,前者对应于TCP,后者对应于UDP。

如何知道将缓冲区传递给recv()__需要多大?

  • SOCK_STREAM:,这真的不是很重要。如果您的协议是事务性/交互性的,那么只需选择一个可以容纳您合理期望的最大单个消息/命令的大小(3000个可能就可以了)。如果您的协议正在传输批量数据,那么更大的缓冲区可能会更有效-一个好的经验法则是与套接字的内核接收缓冲区大小大致相同(通常256kB).
  • SOCK_DGRAM:使用的缓冲区大小足以容纳应用程序级协议发送的最大数据包)。如果你正在使用UDP,那么一般来说,你的应用层协议发送的数据包不应该超过1400字节,因为它们肯定需要分段和重组。

如果recv得到的数据包大于缓冲区,会发生什么情况?

  • SOCK_STREAM:这个问题没有真正的意义,因为流套接字没有数据包的概念-它们只是一个连续的字节流。如果可供读取的字节数超过了缓冲区的空间,则它们将由操作系统排队,供您下次调用recv.
  • SOCK_DGRAM:时使用,多余的字节将被丢弃。

我如何知道我是否收到了完整的消息?

  • SOCK_STREAM:您需要在您的应用层协议中构建某种方法来确定消息的结尾。通常,这要么是长度前缀(以消息的长度开始每个消息),要么是消息结束分隔符(例如,在基于文本的协议中可能只是一个换行符)。第三个较少使用的选项是为每条消息指定固定的大小。这些选项的组合也是可能的-例如,包含长度的固定大小的报头value.
  • SOCK_DGRAM:单个recv调用始终返回单个数据报。

有没有一种方法可以让一个缓冲区没有固定的空间,这样我就可以不断地添加内容,而不用担心空间耗尽?

不是的。但是,您可以尝试使用realloc()调整缓冲区的大小(如果它最初是使用malloc()calloc()分配的)。

票数 248
EN

Stack Overflow用户

发布于 2010-05-19 08:28:03

对于TCP之类的流协议,您几乎可以将缓冲区设置为任何大小。也就是说,推荐使用2的幂的常用值,例如4096或8192。

如果有比你的缓冲区更多的数据,它将被简单地保存在内核中,供你下次调用recv时使用。

是的,你可以继续增加你的缓冲区。您可以从偏移量idx开始对缓冲区的中间位置执行recv操作,您可以这样做:

代码语言:javascript
复制
recv(socket, recv_buffer + idx, recv_buffer_size - idx, 0);
票数 18
EN

Stack Overflow用户

发布于 2010-05-19 08:28:06

如果你有一个SOCK_STREAM套接字,recv只会从流中获取“最多3000个字节”。没有关于缓冲区大小的明确指导:你唯一知道一个流有多大的时候,就是当它都完成的时候;-)。

如果您有一个SOCK_DGRAM套接字,并且数据报大于缓冲区,recv会用数据报的第一部分填充缓冲区,返回-1,并将errno设置为EMSGSIZE。不幸的是,如果协议是UDP,这意味着数据报的其余部分会丢失--这就是UDP被称为TCP不可靠协议的部分原因(我知道有可靠的数据报协议,但它们不是很流行--我不能说出/IP家族中的一个,尽管我非常了解后者;-)。

要动态地增加缓冲区,首先使用malloc分配它,然后根据需要使用realloc。但是,对于来自UDP源的recv,这对您没有帮助。

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2862071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档