0

私の OS X アプリケーションでは、かなり長い間 NSURLRequest を使用して、HTTP 要求をサーバーに送信し、応答を受信して​​きました。次に、Windows と Mac で実行できるように、代わりに libcurl を使用するようにこのコードを移行する必要があります。

どういうわけか、私はそれを機能させることができません...

これが私がやろうとしていることです:

  • HTTP post を使用してサーバーにブロックを送信する
  • サーバーはブロックを評価し、応答を返します
  • 応答の受信、評価、続行 ...

要求とともに送信されたブロックが有効な場合、「アプリケーション/オクテット ストリーム」データ ブロックが要求元のアプリケーションにすぐに送り返されます。ファイルが有効でない場合は、リターン コード 403 が返されます。

投稿リクエストの URL とデータ ブロックをブラウザに直接入力しようとすると、うまくいきます。データ ブロックが有効な場合はファイルがダウンロードされ、そうでない場合は 403 ページが表示されます。

私の libcurl コードは次のようになります。

curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();

if (curl)
{
    struct url_data data;
    data.size = 0;
    data.data = (char*) malloc(4096); /* reasonable size initial buffer */

    if(NULL == data.data)
    {
        fprintf(stderr, "Failed to allocate memory.\n");
        return NULL;
    }

    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(curl, CURLOPT_URL, "<my-url>");
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, [postData cStringUsingEncoding:NSASCIIStringEncoding]);

    curl_slist_append(headerlist, "Content-Type: application/x-www-form-urlencoded");
    curl_slist_append(headerlist, [length cStringUsingEncoding:NSASCIIStringEncoding]);

    curl_easy_setopt(curl, CURLOPT_HEADER, headerlist);

    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);

    curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");

    res = curl_easy_perform(curl);

    if(res != CURLE_OK)
    {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
                         curl_easy_strerror(res));
    }

    curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
}

そして、私の書き込み関数は次のようになります。

struct url_data 
{
    size_t size;
    char* data;
};

size_t write_data(void *ptr, size_t size, size_t nmemb, struct url_data *data)
{
    size_t index = data->size;
    size_t n = (size * nmemb);
    char* tmp;

    data->size += (size * nmemb);

    fprintf(stderr, "data at %p size=%ld nmemb=%ld\n", ptr, size, nmemb);
    tmp = (char*) realloc(data->data, data->size + 1); /* +1 for '\0' */

    memcpy((data->data + index), ptr, n);
    data->data[data->size] = '\0';

    return size * nmemb;
}

ブロックが無効な場合は、正しいリターン コードと 403 ページを受け取ります。有効な場合、応答ブロックを受信して​​いません。書き込み関数が呼び出されることはありません。接続は常にすぐに閉じられます。

誰が私が間違っているのか教えてもらえますか?

libcurl のログ出力の一部を次に示します。

* Adding handle: conn: 0x2a9ee00
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x2a9ee00) send_pipe: 1, recv_pipe: 0
* About to connect() to <my-url> port 80 (#0)
*   Trying <my-url-ip>...
* Connected to <my-url> (<my-url-ip>) port 80 (#0)

このrecv-pipeが問題を引き起こしているのでしょうか? 1にするべきですか?

あなたの考えを聞きたいです!前もって感謝します!

4

2 に答える 2

1

curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);long as パラメータを期待するものを使用してカスタム ヘッダーを渡す必要がありCURLOPT_HEADERます (本文出力にヘッダーを含めない/含めない場合は 0 または 1)。

于 2013-11-13T22:16:58.317 に答える
0

私が見つけた唯一の問題は、あなたが から新しいアドレスを保存していなかったことですrealloc()。確かにクラッシュしますが、write_data()少なくとも一度は呼び出されているはずです。

呼び出されていないことをどのように知っていますか?

write_data()代わりにこれを試してください:

size_t write_data(void *ptr, size_t size, size_t nmemb, struct url_data *data)
{ 
    size_t index = data->size;
    size_t n = (size * nmemb);
    char* tmp;

    data->size += (size * nmemb);

    fprintf(stderr, "data at %p size=%ld nmemb=%ld\n", ptr, size, nmemb);
    tmp = (char*) realloc(data->data, data->size + 1); /* +1 for '\0' */
    if (tmp == NULL) {
        fputs("Error (re)allocating memory", stderr);
        return 0;
    }
    data->data = tmp;

    memcpy((data->data + index), ptr, n);
    data->data[data->size] = '\0';

    return size * nmemb;
}
于 2013-11-13T23:43:06.533 に答える