recv在第二次recv调用后总是读取0个字节

时间:2017-04-30 16:23:04

标签: c windows sockets winsock

我在平台上运行TCP服务器,该平台从缓冲区读取字节,并通过一次发送调用在网络上发送所有字节:

send(sSocket.client_sock, base, frb_size, 0);

frb_size的大小为2_228_224个字节。

在接收端,我试图缓冲数据:

while(1) {
    while(total != size) {
        r = recv(my_socket->sock, buf, 8192-total, 0);
        memcpy(buffer+total, buf, r);
        total += r;
    }
  //some code dealing with manipulating the buffer with SDL
}

我有一个较小的缓冲区buf,大小为8192.读取时,它使用memcpy将其放入缓冲区内的正确位置,大小为2_228_224。

我的问题是,在第一次迭代之后,所有进行的迭代都返回r为0,这意味着套接字已按文档关闭。同样奇怪的是,无论我使用什么大小的buf,它总是在第一次迭代时返回完整的字节数。例如,在上面的代码中将返回8192个字节,如果我将大小更改为65507,它将返回65507,但如果我将其更改为2_228_224,它将永远不会返回完整的缓冲区。

与此同时:

while(1) {
   r = recv(my_socket->sock, buffer, size, 0);
  //some code dealing with manipulating the buffer with SDL
}

其中size是缓冲区的大小(2_228_224)。 r在调试时永远不会返回0,但它也不会有构成发送输入的完整字节数。

我在Windows上的套接字API上做错了吗?有没有办法让Winsock套接字阻塞直到收到所有字节数?

感谢。

1 个答案:

答案 0 :(得分:2)

正如评论中所述,使用8192-total是不对的。要准确读取size个字节,请使用以下内容:

while(total < size) {
    int bytes = size - total;
    if (bytes > 8192) bytes = 8192;
    r = recv(my_socket->sock, buf, bytes, 0);
    if (r <= 0) {
        /* handle this! */
        break;
    }
    memcpy(buffer+total, buf, r);
    total += r;
}

在每次迭代时,它会尝试读取总数中剩余的字节数,但是会以输入缓冲区的大小为上限。

在循环中处理r <= 0break以避免无限循环(如果重复r == 0)或段错误(如果r == -1重复推送{{} 1}}否定)。