gpt4 book ai didi

c - recv()对于大量数据不起作用

转载 作者:太空宇宙 更新时间:2023-11-04 02:55:45 25 4
gpt4 key购买 nike

我正在使用新设计的协议(protocol)实现一台服务器。根据协议(protocol),客户端发送 header 后跟数据。 header 包含元信息,包括数据大小

我们提供示例客户端,但客户端程序也可以由第三方编写。因此,我们不能完全依赖 header 中提供的数据大小字段。

现在,我遇到了 recv() 系统调用的一个问题。

      #define SOCKET_CHUNK_SIZE 4096
void * value;

1 value = (void *) malloc(hdr.size);
2 total_bytes_read = 0;
3 while(total_bytes_read < hdr.size) {
4 n = recv(newsockfd, value + total_bytes_read, SOCKET_CHUNK_SIZE, 0);
5
6 //fprintf(stderr, " %ld + %d = %ld\n", total_bytes_read, n, total_bytes_read + n);
7
8 total_bytes_read += n;
9
10 if(n == 0 || n < SOCKET_CHUNK_SIZE)
11 break;
12 if(n < 0)
13 send_error_response(newsockfd);
14 }
15
16 fprintf(stderr, "%ld", total_bytes_read);

这对于少量数据(如 9420 字节)非常有效,但对于大量数据则失败。

观察:

让客户端发送一些大数据,比如 604697 字节(hdr.size):

  1. recv() 只能读取 65280 字节。即第 16 行的 fprintf 打印 65280。(我在我的机器上检查了 SSIZE_MAX,它是 2147483647,所以它比 SOCKET_CHUNK_SIZE 大得多)

  2. 我尝试在 recv() 调用中使用 MSG_DONTWAIT 标志,但结果是一样的。

  3. 我尝试使用 read() 系统调用代替 recv(),结果是一样的。

  4. 当我取消对第 6 行的注释时,它工作得很好!! (但是这一行(和第 16 行)仅用于调试目的。我不能将其保留在最终版本中)

  5. 如果我在 recv() 中使用 MSG_WAITALL 标志,它会工作,但在读取最后一个 block 时会阻塞,因为最后一个 block 大小小于 SOCKET_CHUNK_SIZE (604697 = 147 * 4096 + 2585)。因此,我无法使用此标志,除非我依赖客户端 header 中提供的 size 并在 recv() 中进行更改。

客户端提供的数据也可以是二进制的,所以我们不能放置某种指示作为数据的结尾。

欢迎任何有想法/解决方案的人。正如我提到的,我们有解决方案 - 依赖客户端 header - 但只有在我找不到任何其他方法时我才会更喜欢它。

拉维

最佳答案

几乎所有的观察结果都可以完美解释:

  1. 我想跳过那个,因为我不确定我是否理解正确,而且我现在认为它是一个次要错误。
  2. recv 不能保证填满整个缓冲区(除非您设置 MSG_WAITALL)。它在接收到一些字节后返回。因此,如果您不设置 MSG_WAITALL,第 10 行中的第二部分条件将阻止您接收更多数据。设置 MSG_WAITALL 使 recv 仅在整个缓冲区填满后返回(在您的情况下为 SOCKET_CHUNK_SIZE)。由于您的有效负载大小并不总是 SOCKET_CHUNK_SIZE 的倍数,因此您最后的 recv 调用将挂起,直到连接终止。
  3. 这是由于我上面提到的第 10 行的情况。
  4. 坚持使用 recv,这是正确的方法
  5. 我想取消注释第 6 行会改变执行时间,这样偶然比 SOCKET_CHUNK_SIZE 更多的数据到达套接字。

因此,从我的角度来看,最好的办法是使用没有 MSG_WAITALL 标志的 recv 并接受小于 SOCKET_CHUNK_SIZE 的接收 block 。

关于c - recv()对于大量数据不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17647149/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com