确定使用recv读取的字节数

时间:2012-11-14 20:36:59

标签: c winsock recv

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

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

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;
}

要将数据打印到stdout我只使用for循环:

//t_html->data_sz points to my data->data_sz structure
//t_html->data points to my data->data structure
for(i = 0; i <= t_html->data_sz; i++) (void)fputc((int)t_html->data[i], stdout);

以上代码适用于某些网站但未通过其他网站(例如,在查询http://www.google.com时,我希望最终字符为</html>,但我得到</html>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);
}

1 个答案:

答案 0 :(得分:1)

  1. recv(sock, data->data + data->data_sz, CHUNKSIZE, 0)可能是个问题。为什么?因为缓冲区中可能没有CHUNKSIZE个空间。您实际上已离开databff - data->data_sz(假设data被分配为databff的大小)。这一切都取决于databffCHUNKSIZE的初始值,我无法看到这些值,并且我会指出这是为了以防万一。
  2. 不保证数据以NULL字符终止。您的打印循环显示i <= t_html->data_sz;这是错误的。它应该是i < t_html->data_sz;。如果您使用<=,那么您将通过缓冲区访问一个,这可能是您有时会得到一个奇怪的角色的原因,有时则不是。