范围下载http

时间:2015-10-25 12:53:01

标签: c++ sockets get request range

我需要以块的形式下载一个html页面。我已经构建了一个GET reuest,可以下载一定范围的数据。但我不能以重复的方式做到这一点。 基本上我必须首先收到0-99字节然后100-199等等...... 另外,我很高兴知道如何使用c或c ++代码预先知道接收文件的确切大小。 以下是我的代码。 我已经成功地将连接器豁免到插座等。

int c=0,s=0;
while(1)
{
    get = build_get_query(host, page,s);
    c+=1;
    fprintf(stderr, "Query is:\n<<START>>\n%s<<END>>\n", get);
    //Send the query to the server
    int sent = 0;
    cout<<"sending "<<c<<endl;
    while(sent < strlen(get))
    {
        tmpres = send(sock, get+sent, strlen(get)-sent, 0);
        if(tmpres == -1)
        {
            perror("Can't send query");
            exit(1);
        }
        sent += tmpres;
    }
    //now it is time to receive the page
    memset(buf, 0, sizeof(buf));
    int htmlstart = 0;
    char * htmlcontent;
    cout<< "reciving "<<c<<endl;
    while((tmpres = recv(sock, buf, BUFSIZ, 0)) > 0)
    {
        if(htmlstart == 0)
        {
            /* Under certain conditions this will not work.
            * If the \r\n\r\n part is splitted into two messages
            * it will fail to detect the beginning of HTML content
            */
            htmlcontent = strstr(buf, "\r\n\r\n");
            if(htmlcontent != NULL)
            {
                htmlstart = 1;
                htmlcontent += 4;
            }
        }
        else
        {
            htmlcontent = buf;
        }
        if(htmlstart)
        {
            fprintf(stdout, htmlcontent);
        }

        memset(buf, 0, tmpres);
    }
    if(tmpres < 0)
    {
        perror("Error receiving data");
    }
    s+=100;
    if(c==5)
        break;
}


char *build_get_query(char *host, char *page,int i)
{
char *query;
char *getpage = page;

int j=i+99;
char tpl[100] = "GET /%s HTTP/1.1\r\nHost: %s\r\nRange: bytes=%d-%d\r\nUser-    Agent: %s\r\n\r\n";

if(getpage[0] == '/')
{
    getpage = getpage + 1;
    fprintf(stderr,"Removing leading \"/\", converting %s to %s\n", page,  getpage);
}

query = (char     *)malloc(strlen(host)+strlen(getpage)+8+strlen(USERAGENT)+strlen(tpl)-5);
sprintf(query, tpl, getpage, host, i , j, USERAGENT);
return query;
}

1 个答案:

答案 0 :(得分:2)

  

另外,我很高兴知道如何使用c或c ++代码预先知道接收文件的确切大小。

如果服务器支持对特定资源的范围请求(无法保证),那么答案将如下所示:

 HTTP/1.1 206 partial content
 Content-Range: bytes 100-199/12345

这意味着响应将包含字节100..199,并且内容的总大小为12345字节。

这里有很多问题涉及解析HTTP头,因此我不会详细介绍如何专门使用C / C ++从头中提取这些数据。

另请注意,您正在执行HTTP / 1.1请求,因此必须处理可能的分块响应并隐式保持活动状态。我真的建议使用现有的HTTP库,而不是手动完成并做错。如果您真的想自己实施,请学习the specification of HTTP