Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
recv()用于无法工作的较大数据量_C_Sockets_Network Programming_Recv - Fatal编程技术网

recv()用于无法工作的较大数据量

recv()用于无法工作的较大数据量,c,sockets,network-programming,recv,C,Sockets,Network Programming,Recv,我正在用新设计的协议实现一台服务器。按照协议,客户机发送头,后跟数据。标头包含元信息,包括数据大小 我们提供示例客户端,但客户端程序也可以由第三方编写。所以,我们不能完全依赖于报头中提供的数据字段的大小 现在,我面临一个有关recv()系统调用的问题 #define SOCKET_CHUNK_SIZE 4096 void * value; 1 value = (void *) malloc(hdr.size); 2 total_bytes_read =

我正在用新设计的协议实现一台服务器。按照协议,客户机发送头,后跟数据。标头包含元信息,包括数据大小

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

现在,我面临一个有关
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);
#定义套接字块大小4096
无效*值;
1值=(void*)malloc(hdr.size);
2总字节数\u读取=0;
3 while(总字节读取
这对少量数据(如9420字节)非常有效,但对较大数据量无效

观察:

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

  • recv()
    只能读取65280字节。i、 e.fprintf在线打印16张65280张。(我在我的机器上检查了SSIZE_MAX,它是2147483647,所以它远远大于SOCKET_CHUNK_大小)

  • 我尝试在
    recv()
    调用中使用MSG_DONTWAIT标志,但结果相同

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

  • 当我取消注释第6行时,它工作得非常好!!(但这一行(以及第16行)仅用于调试目的。我无法将其保留在最终版本中)

  • 如果我在
    recv()
    中使用MSG_WAITALL标志,它可以工作,但在读取最后一个块时会阻塞,因为最后一个块大小小于套接字块大小(604697=147*4096+2585)。所以,我不能使用这个标志,除非我依赖于客户端头中提供的大小并在
    recv()
    中进行更改

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

    欢迎任何有想法/解决方案的人。正如我所提到的,我们有一个解决方案——依赖于客户端头——但我只会在找不到其他方法的情况下选择它


    拉维

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

  • 我想跳过这一个,因为我不确定我是否得到了正确的,因为我认为这是一个次要的错误,现在
  • recv不能保证填满整个缓冲区(除非您设置MSG_WAITALL)。它在接收到一些字节后返回。因此,第10行中条件的第二部分是,如果不设置MSG_WAITALL,将阻止您接收更多数据。设置MSG_WAITALL将使recv仅在整个缓冲区填满后返回(在您的示例中为SOCKET_CHUNK_SIZE)。由于有效负载的大小并不总是SOCKET\u CHUNK\u大小的倍数,因此您的最后一次recv呼叫将一直挂起,直到连接断开
  • 这是由于我上面提到的第10行中的情况
  • 坚持使用recv,这是正确的方法
  • 我猜取消注释第6行会改变执行的时间,这样一来,偶然地,比SOCKET\u CHUNK\u大小更多的数据到达SOCKET

  • 因此,从我的观点来看,最好的办法是在不使用MSG_WAITALL标志的情况下使用recv,并接受小于SOCKET_CHUNK_SIZE的接收块。

    n
    此条件不好。一个
    recv
    调用接收的数据可以小于指定的字节数。在知道
    n>0
    之前,不应增加
    total\u bytes\u read
    。如果
    n<0
    它将发送错误并且不接受data@Ravi如果
    n<0
    执行
    total\u bytes\u read+=n
    是不正确的。没有两条路可走。您应该先测试
    n<0