【问题标题】:Why would recv fail when the requested buffer size is greater than the amount of data available?当请求的缓冲区大小大于可用数据量时,为什么 recv 会失败?
【发布时间】:2010-10-01 06:42:29
【问题描述】:

TCP 传输堆栈的基础是其作者有时记录的许多缓冲区限制。在 WinXP SP3 上,我想我遇到过其中一种情况,但不知道为什么。

我已经实现了一个简单的客户端来从服务器获取数据(由一位同事用 Java 编写)。该协议是将数据的长度(按网络顺序)写入四个字节,然后写入数据。服务器将数据以 1024 字节块的形式写入 TCP 流。客户端正确接收到数据缓冲区的长度,分配内存,循环重复调用recv获取所有数据:

unsigned int TCP_BlockSize = 4096;
unsigned int len;
int result;

...code to request len...
unsigned char *buf = new unsigned char[len];

if( len > TCP_BlockSize)
{
Uint32 currentLen = 0;
result = 0;
Uint32 failCount = 0;
while( currentLen < len && result >= 0)
{
        result = recv( sock, buf + currentLen, TCP_BlockSize );
        if( result > 0 )
    {
        currentLen = currentLen + result;
    }
    else
        {
    break;
        }
}
}

如果我将 TCP_BlockSize 设置为 4095 或以下,一切都很好,我可以接收数兆字节的传输。当我尝试 4096 大小的接收块时,对剩余数据的最后一个请求,即 len - currentLen 另一个细节:服务器在发送最后一个字节后关闭套接字。这就引出了一个问题,为什么不返回剩余的数据?在流为空并且关闭之前不从recv返回-1感觉像是一种缺陷,因为当流不为空并且关闭以接收时它是模棱两可的 - 1来自recv。

那么如何获取最后的数据呢?

【问题讨论】:

  • 尼古拉斯·曼库索的回答是正确的,解决了问题。谢谢!

标签: windows winapi tcp winsock


【解决方案1】:

尝试类似...

to_rcv = (len - currentlen < TCP_BlockSize) ? len - currentlen : TCP_BlockSize;
result = recv( sock, buf + currentLen, to_rcv);

这样,最终的 recv 将只要求所需的数量,否则它将要求 TCP_BlockSize。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    • 2015-06-28
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    相关资源
    最近更新 更多