【问题标题】:Missing chunk size in chunked HTTP response using libcurl使用 libcurl 的分块 HTTP 响应中缺少块大小
【发布时间】:2012-10-17 09:02:02
【问题描述】:

我尝试使用 curl 库来构建 HTTP 代理。我现在面临的问题是分块的 HTTP 响应不正确。通过检查保存的 HTTP 响应文件,我发现 HTTP 响应开始和结束时的块大小丢失了。 HTTP 响应来自 curl 回调函数,如下所示。

size_t httpClient::write_data(char *ptr, size_t size, size_t nmemb, void* userdata)
{   

    // get total size   
    size_t realsize = size*nmemb;
    // get object
    struct MemoryStruct* mem = (struct MemoryStruct*)userdata;

    // size of memory block pointerd by the mem->memory is changed to the new bytes
    mem->memory = (char*)realloc(mem->memory, (mem->size + realsize));

    if(mem->memory == NULL)
    {
        printf("not enough memory (realloc returned NULL)\n");
            exit(1);
    }

    // copy to memory structure
    memcpy(&(mem->memory[mem->size]), ptr, realsize);
    mem->size += realsize;
    //mem->memory[mem->size] = 0;

    cout<<"Write ["<<realsize<<"] bytes Data to chunk"<<endl;
    return realsize;

}

希望有人能指出我为这个回调函数犯的错误。谢谢:D

预期的分块 HTTP 响应如下所示:

HTTP/1.1 200 OK^M
Date: Wed, 17 Oct 2012 07:44:54 GMT^M
Expires: -1^M
Cache-Control: private, max-age=0^M
Content-Type: text/html; charset=UTF-8^M
Set-Cookie: PREF=ID=58da9f2271ea2d2b:FF=0:TM=1350459894:LM=1350459894:S=EnJS1hQo2d6_AnPM; expires=Fri, 17-Oct-2014 07:44:54 GMT; path=/; domain=.google.com^M
Set-Cookie: NID=65=RW0txpQSNA4NwlRhp0y1I6iF3L0xfugw8Bv4GMsB1yE1qu7iGoBO_2ZxqS0-DSeS4tJKnV26JlfVZmsnjxnjdUaHTDj3-AFREsvyMiE8wSKyabwYG8x-e18Pj8smdxUs; expires=Thu, 18-Apr-2013 07:44:54 GMT; path=/; domain=.google.com; HttpOnly^M
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."^M
Content-Encoding: gzip^M
Transfer-Encoding: chunked^M
Server: gws^M
X-XSS-Protection: 1; mode=block^M
X-Frame-Options: SAMEORIGIN^M
^M
907a^M

十六进制格式的数字 907a 是我的 HTTP 响应文件中遗漏的块大小。

【问题讨论】:

    标签: c++ http curl


    【解决方案1】:

    我可以向你提出下一步的建议:

    1. 进入您的代码部分,设置回调函数,在堆栈上创建struct MemoryStruct
    2. 将参数写入回调函数原型中,以 struct MemoryStruct *userdata 代替 void *userdata
    3. 您的代码将如下所示:

      MemoryStruct data;
      curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
      curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_data);
      
      ---------------------------------------------------------------------
      // if you'll used std::string instead char*
      ---------------------------------------------------------------------
      size_t write_data(char *data, size_t size, size_t count, MemoryStruct *userdata)
      {
          int result = 0;
          if(userdata->memory != NULL) {
              userdata->memory->append(data, size*count);
              result = size*count;
              userdata->size += result;
          }
          return result;
      }
      

    调用curl库curl_easy_perform(CURL *handler)的函数后可以得到正确的响应。

    PS。如果我对您的问题的理解有误,请在调用回调函数的位置显示您的代码

    【讨论】:

    • 谢谢鲁。我确实创建了 MemoryStruct 并设置了相应的 curl_easy_setopt()。我想使用 char 而不是 string 的原因是一些 HTTP 响应包含纯字节。如果使用字符串,会丢失一些数据。
    • ShadowScorpion,作为一项规则,HTTP 响应包含来自 ASCII 符号,因此您可以使用 std::string。如果您的 HTTP 响应可能包含纯字节,则应使用 std::vector,因为在您的情况下使用 realloc 非常危险。希望对你有帮助。
    • Ruu,再次感谢您的澄清。我知道 HTTP 标头在 ASCII 符号下,而块 HTTP 的消息正文都是纯字节数据。因此,我必须使用 char*。既然你提到realloc是危险的,你能再具体解释一下吗?
    • ShadowScorpion,你使用了 realloc 的显式内存分配,它对构造函数/析构函数和你的内存块一无所知。 Realloc 将尝试调整当前分配的内存块的大小。如果不能,它将分配一个新的内存块,复制指针的内容并返回一个指向结构的新指针。然后 vector 可以控制你的内存分配,为你的程序安全。此外,vector 可以在其中调用构造函数/析构函数。使用 std::vector 或其他 C++ 标准库的动态容器,它们会根据您的需要自动增长。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    • 2018-03-03
    • 2012-10-21
    • 1970-01-01
    相关资源
    最近更新 更多