2012-03-27 3 views
1

memcpy()関数を使ってread()から取得したバイナリデータをバッファに格納しようとしています。memcpy()関数の使い方は?

基本的に、私は自分のバッファにBUFを格納したい:私は( "%sの"、バッファ)のprintfとき

#define MAX_BUFFER_SIZE 256 
//... 
char * 
httpget(const char * domain, const int port, const char * headers) 
{ 
    int sockfd; 
    int buf_size = MAX_BUFFER_SIZE; 

    struct sockaddr_in sock_addr; 
    struct hostent * host; 

    char * buffer; 
    char * newbuf; 
    char * tbuf; 

    sockfd = socket(AF_INET,SOCK_STREAM,0); 

    if(sockfd == -1) 
    { 
     return NULL; 
    } 

    host = gethostbyname(domain); 

    if(NULL == host) 
    { 
     close(sockfd); 
     return NULL; 
    } 

    memset(&sock_addr, '\0', sizeof(sock_addr)); 
    sock_addr.sin_family = AF_INET; 
    memcpy(&sock_addr.sin_addr.s_addr, 
      host -> h_addr, 
      host -> h_length); 

    sock_addr.sin_port = htons(port); 

    if(connect(sockfd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) == -1) 
    { 
     close(sockfd); 
     return NULL; 
    } 

    if(write(sockfd, headers, strlen(headers) + 1) == -1) 
    { 
     close(sockfd); 
     return NULL; 
    } 

    buffer = malloc(MAX_BUFFER_SIZE); 
    tbuf = malloc(MAX_BUFFER_SIZE); 

    if(buffer == NULL || tbuf == NULL) 
    { 
     return NULL; 
    } 

    int bytesloaded = 0; 
    int readed; 

    while((readed = read(sockfd, tbuf, MAX_BUFFER_SIZE)) > 0) 
    { 
     if(bytesloaded + readed >= buf_size) 
     { 
      buf_size = buf_size + MAX_BUFFER_SIZE; 
      newbuf = realloc(buffer, buf_size); 

      if(newbuf != NULL) 
      { 
       buffer = newbuf; 
      } 
      else 
      { 
       return NULL; 
      } 
     } 

     memcpy(buffer, tbuf, readed); 
     bytesloaded += readed; 
    } 

    close(sockfd); 
    printf("buffer = %s", buffer); 
    return buffer; 
} 

けど。私はHTTPヘッダと�PNGキャラクタの長さが7007のバイナリからしか得られません。これを修正する方法は?私はこれがあなたにとってはっきりしていることを望みます。どのような助けも非常に高く評価されています。

+0

この再入力されたコードですか?'buffe'は、コンパイラがキャッチするタイプミスのように見えます。短縮されたコードが本当に失敗するのは本当に良いことです。このWebサイトだけに存在するコードをデバッグするのは楽しいことではありません... – sarnold

+2

2番目のメモリ割り当てが失敗した場合、最初のメモリ割り当てで割り当てられた256バイトがリークします。 – sarnold

+0

@sarnold:タイプミスでした。私は実際のコードを追加しました。 – Jack

答えて

3

私はあなたがしたいと思う:

memcpy(buffer + bytesloaded, buf, readed); 

あなたが応答して送信されて.png画像がnullを含む可能性のバイナリデータであるため、printf("%s",buffer)を使用して、それをダンプしようとすると、全体の応答が表示されません'\0'バイト、その時点でprintf()が停止します。

レスポンスで返されるデータ(またはその情報)を調べるための他のさまざまなオプションがあります。デバッガのbufferを参照し、bytesloaded変数をダンプし、bufferを16進数に変換する関数を使用してダンプします。レスポンス本文(ヘッダーとヘッダーに続くCR/LFの後ろ)を.pngファイルに書き出し、表示したり、書き込んだりして、画像を表示するものを見てください。

+0

私のコードを更新します。チェックアウト。 'HTTP/1.0 200 OK 日付:Tue、27 Mar 2012 01:01:54 GMT サーバ:Mono.WebServer2/0.2.0.0 Unix 最終更新日:太陽、25日2012年午後02時50分48秒GMT X-ASPNET-バージョン:2.0.50727 のContent-Length:7007 のCache-Control:プライベート のContent-Type:画像/ PNG 接続:近い PNG ' – Jack

+0

@Jack :私の更新された答えを見てください。 –

1

memcpyにtypoがあります。バッファの代わりにbuffeを参照していますが、実際のコードではなく、投稿にのみ表示される可能性があります(コンパイルされていないと思います)それは間違いなく問題です。

UPDATE:他の回答は、ヌルバイトが存在する可能性があると示唆していますが、pngヘッダー仕様ではヌルバイトがヘッダーの一部である必要がないため、ボディは唯一の場所ですが、あなたがデータを受け取っていない場合、唯一の選択肢は身体の中の最初のものであるかもしれませんが、私は実際にリアケースであると信じているので、別の画像や別のURLのような別の情報源で試してみるかもしれません。問題はすべてのpngイメージに残っています。それはprintfとヘッダーの間にあります(ヘッダーにヌルバイトがある場合は、それはとにかく侵入する価値があります)。

しかし、PNGの後にCRLFが来てEOFが来ることに注意してください。また、printfに問題がある場合は面白いかもしれませんが、それでも問題が解決しない場合は、あなたがpngビューアでそれを開いていないかのいずれかです。

実際にはあなたのソケットソースは含まれていません。あなた自身が書いたコードであれば、それが最初のEOFで停止していないことを確認してください。

+0

私のコードを更新します。チェックアウト。 :) – Jack

+0

答えを更新しました –

1

printf(3)フォーマット指示文%sは、ASCII NUL文字が出現するまで、バイトを文字として出力します。 PNG formatは、おそらく、第9バイト - 最初の8バイトが0x89,PNG、次にいくつかのホワイトスペース文字が特定の種類のホワイトスペースマングリングを検出するとすぐに、NULを許可する可能性があります。

別のprintf(3)フォーマット指定子を使用して問題のデータを表示するか、デバッグファイルに書き込むことをお勧めします。そのため、一般的な16進エディタで編集してその内容を検証できます。