关于C中的套接字库,我有几个问题。下面是我将在问题中引用的代码片段。
char recv_buffer[3000];
recv(socket, recv_buffer, 3000, 0);
recv()
收到的数据包比我的缓冲区大会发生什么?strcat
将最新的recv()
响应连接到缓冲区?我知道这其中有很多问题,但如果有任何回应,我会非常感激。
发布于 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()
分配的)。
发布于 2010-05-19 08:28:03
对于TCP之类的流协议,您几乎可以将缓冲区设置为任何大小。也就是说,推荐使用2的幂的常用值,例如4096或8192。
如果有比你的缓冲区更多的数据,它将被简单地保存在内核中,供你下次调用recv
时使用。
是的,你可以继续增加你的缓冲区。您可以从偏移量idx
开始对缓冲区的中间位置执行recv操作,您可以这样做:
recv(socket, recv_buffer + idx, recv_buffer_size - idx, 0);
发布于 2010-05-19 08:28:06
如果你有一个SOCK_STREAM
套接字,recv
只会从流中获取“最多3000个字节”。没有关于缓冲区大小的明确指导:你唯一知道一个流有多大的时候,就是当它都完成的时候;-)。
如果您有一个SOCK_DGRAM
套接字,并且数据报大于缓冲区,recv
会用数据报的第一部分填充缓冲区,返回-1,并将errno设置为EMSGSIZE。不幸的是,如果协议是UDP,这意味着数据报的其余部分会丢失--这就是UDP被称为TCP不可靠协议的部分原因(我知道有可靠的数据报协议,但它们不是很流行--我不能说出/IP家族中的一个,尽管我非常了解后者;-)。
要动态地增加缓冲区,首先使用malloc
分配它,然后根据需要使用realloc
。但是,对于来自UDP源的recv
,这对您没有帮助。
https://stackoverflow.com/questions/2862071
复制相似问题