2011-11-12 27 views
0

作業ではないかもしれない可能性の重複:
Using HTTP authentication with libcurl in C for Twitter Streaminglibcurlのコールバック関数は、Twitterのストリーミング用

私は、ストリーミングAPIからのツイートのストリームを受信するCコードを記述することができました。しかし、ストリームは以下のコードで出力されません(出力なし)。このコードは、CURLOPT_URLがgoogle.comまたは9gag.comに設定されている場合に機能します。私は、問題が、受信した膨大なデータを持つつぶやきの安定した流れと関係していると思います。レスポンス(ストリーム)を出力するwrite_funcコールバック関数が動作していない可能性があります。なぜ出力がないのでしょうか? 私は、コールバック関数がおそらくTwitter APIによって送信された膨大なストリームに圧倒されていると考えています。これが正しい場合は、適切な書き込みコールバック関数をどのように書くべきですか?

お願いします。コードを実行するたびに、システムモニタのネットワーク履歴が受信バイトで上昇するのを見ているので、ストリームの受信が機能していることを確認しました。

ありがとうございます!

コード:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <curl/curl.h> 

struct string { 
    char *ptr; 
    size_t len; 
}; 

void init_string(struct string *s) { 
    s->len = 0; 
    s->ptr = malloc(s->len+1); 
    if (s->ptr == NULL) { 
    fprintf(stderr, "malloc() failed\n"); 
    exit(EXIT_FAILURE); 
    } 
    s->ptr[0] = '\0'; 
} 

size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s) 
{ 
    size_t new_len = s->len + size*nmemb; 

    s->ptr = realloc(s->ptr, new_len+1); 
    if (s->ptr == NULL) { 

    fprintf(stderr, "realloc() failed\n"); 
    exit(EXIT_FAILURE); 
    } 
    memcpy(s->ptr+s->len, ptr, size*nmemb); 
    s->ptr[new_len] = '\0'; 
    s->len = new_len; 

    return size*nmemb; 
} 

int main(void) 
{ 
    CURL *curl; 
    CURLcode res; 

    curl = curl_easy_init(); 
    if(curl) { 
    struct string s; 
    init_string(&s); 

    curl_easy_setopt(curl, CURLOPT_URL, "https://stream.twitter.com/1/statuses/sample.json"); 
    curl_easy_setopt(curl, CURLOPT_USERPWD, "neilmarion:password_here"); 
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); 
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); 
    res = curl_easy_perform(curl); 

    printf("%s\n", s.ptr); 
    free(s.ptr); 

    /* always cleanup */ 
    curl_easy_cleanup(curl); 
    } 
    return 0; 
} 

答えて

3

OK、私はいくつかのテストを行なったし、URLだけで、完了していないようデータを送信し続けることが表示されます。私は15M後にそれを殺しました。しかし、あなたがコールバックにprintステートメントを置くか、straceを使うと、正しく動作することがわかります。あなたの文字列sは成長し続けています。

1つの解決策は、コールバックを変更してsが一定のサイズに達すると印刷して再初期化することです。それ以外の場合は、プログラムが最終的にメモリ不足になるようです。コールバックを

size_t max_buffer = 10240; // 10K 
size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s) 
{ 
    size_t new_len = s->len + size*nmemb; 

    s->ptr = realloc(s->ptr, new_len+1); 
    if (s->ptr == NULL) { 
    fprintf(stderr, "realloc() failed\n"); 
    exit(EXIT_FAILURE); 
    } 
    memcpy(s->ptr+s->len, ptr, size*nmemb); 
    s->ptr[new_len] = '\0'; 
    s->len = new_len; 
    // Begin newly added code 
    if(s->len >= max_buffer) 
    { 
    printf("%s", s->ptr); 
    fflush(stdout); 
    free(s->ptr); 
    initString(s); 
    } 
    // End newly added code 
    return size*nmemb; 
} 

に変更して、最後に印刷してください。最後のビットと最後の改行をダンプします。バッファリングされたソリューションが得られたので、動的に追加されたメモリを必要としない、より効率的な実装を検討することができます。

+0

正確に。それは終了しません。コールバック関数が上記の目的には適していないことを確認していただきありがとうございます。アイデアがあれば、正しいコールバック関数を投稿できますか?ありがとう。 – neilmarion

+1

例コールバックコード – Sodved

+1

メモリマップされたファイルを使用するのは簡単かもしれませんが、スピードを犠牲にして数GBのストレージを提供したり、蒸気を複数のチャンクに分割したり(これを使用するプロジェクトの場合)、オンザフライで処理するためにそれらをディスパッチします。 – Necrolis

関連する問題