确定使用recv读取的字节数

确定使用recv读取的字节数,c,winsock,recv,C,Winsock,Recv,我对recv有问题。我编写了一个函数,用数据填充结构,并从套接字读取数据的长度(以字节为单位) 为了进行测试,我只是根据recv读取的字节总数,将数据逐字节打印到stdout。由于某些原因,读取的字节数有时似乎是正确的,有时则不正确,这取决于我查询的站点。例如,以下代码在某些站点上按预期工作: data->data_sz = 0; while((i = recv(sock, data->data + data->data_sz, CHUNKSIZE, 0)) > 0) {

我对
recv
有问题。我编写了一个函数,用数据填充结构,并从套接字读取数据的长度(以字节为单位)

为了进行测试,我只是根据
recv
读取的字节总数,将数据逐字节打印到
stdout
。由于某些原因,读取的字节数有时似乎是正确的,有时则不正确,这取决于我查询的站点。例如,以下代码在某些站点上按预期工作:

data->data_sz = 0;
while((i = recv(sock, data->data + data->data_sz, CHUNKSIZE, 0)) > 0)
{
    data->data_sz += i;
    if(databff - data->data_sz < CHUNKSIZE)
    {
        databff *= 2;
        if(!(tmp = realloc(data->data, databff)))
        {
            free(data->data);
            (void) WSACleanup();
            return 0;
        }
        data->data = tmp;
    }
}
i = strsbstr(data->data, "\r\n\r\n") + 4;                   //i = the position of the first char after header info  
if(i >= 0)  
{
    data->data_sz = data->data_sz - i;                      //data->data_sz = number of bytes without header info
    memmove(data->data, data->data + i, data->data_sz);
    if(!(tmp = realloc(data->data, data->data_sz)))
    {
        free(data->data);
        (void)WSACleanup();
        return 0;
    }
        data->data = tmp;                       
    }
    else
    {
        free(data->data);
        (void) WSACleanup();
        return 0;
    }
    return 1;
}
上述代码适用于某些站点,但在其他站点上失败(例如,当查询
http://www.google.com
我希望最后的字符是
,但我得到了
l

基本上我的问题是,
data->data_sz
(接收的字节数)没有正确计算,这使得无法正确使用收集的数据。我现在真的不知道该怎么办

编辑: 下面是在上述代码中调用的
strsbstr
函数:

int strsbstr(const char *str, const char *sbstr)
{
    char *sbstrlc;

    if(!(strcmp(str, sbstr))) return 0;
    if(!(sbstrlc = strstr(str, sbstr))) return -1;
    return (int) (sbstrlc - str);
}
  • recv(sock,data->data+data->data_sz,CHUNKSIZE,0)
    可能是一个问题。为什么?因为您的缓冲区中可能没有
    CHUNKSIZE
    空间。实际上,您在左边有
    databff-data->data_sz
    (假设
    data
    分配给
    databff
    的大小)。这一切都取决于
    databff
    CHUNKSIZE
    的初始值,我看不到它们,我想指出这一点以防万一

  • 数据不保证以空字符结尾。您的打印循环显示
    i data_sz哪个是错误的。它应该是
    idata\usz。如果您使用
    ,是否可以发布一个可编译的程序,而无需添加样板文件和您遗漏的非标准函数(例如
    WSACleanup()
    )?这将使回答您的问题更容易。WSACleanup()是一个Winsock函数。我不知道你是什么意思?我会更新我的帖子来展示strsbstr正在做什么(如果你是这个意思的话)?对不起。到目前为止,我只使用了Unix套接字,因为您没有提供任何包含,所以我无法看到它是来自Windows的函数。不过,如果代码实际上是可编译的(而不是片段),那么调试代码就容易多了。@fuzzxl:它被标记为“winsock”。请注意:
    i=strsbstr(data->data,“\r\n\r\n”)+4;如果(i>=0)
    =3
    。您应该检查
    i>=4
    ,或者在测试后推迟添加4。非常感谢!它现在似乎在工作,我觉得有点傻,我错过了,但我不在乎这一点。非常感谢你!很高兴我能帮忙!小细节是魔鬼。我确定了我的第一点;我刚刚意识到我把“实际尺寸”写错了。
    int strsbstr(const char *str, const char *sbstr)
    {
        char *sbstrlc;
    
        if(!(strcmp(str, sbstr))) return 0;
        if(!(sbstrlc = strstr(str, sbstr))) return -1;
        return (int) (sbstrlc - str);
    }