2

C とソケットを使用して独自のダウンロード マネージャーをコーディングしようとしましたが、奇妙なことが起こり、その理由を説明できません。

つまり、ソケットを作成し、サーバーに接続し、GET リクエストを作成して送信します。これまでのところすべて順調です。ダウンロードが開始され、終了したら、byte(char) 配列で '\n\r\n' を検索して、ヘッダーの最後に到達します (メッセージ本文の開始にはさらに 1 つ)。そこから、msg_size-(header_end+1) バイトをファイルに書き込みます。結果のファイルは、ファイルを定期的にダウンロードした場合とまったく同じバイトサイズになります。しかし、それを抽出しようとすると、「予期しないファイルの終わり」でエラーが発生しますが、他のバージョンは問題なく抽出されます。

誰かがそれについての説明を持っているかもしれません。コードを提供することもできます。問題がどこにあるのかわからないので、最初に問題を言語化しようとしていました。私はすでに "wb" と "w" フラグを試しました。

また、サーバーはチャンク転送または圧縮エンコーディングを指定しません。ただし、http/1.1 です。

ありがとう!

編集:これはサーバーヘッダーです:

HTTP/1.1 200 OK
Date: Mon, 20 May 2013 16:33:26 GMT
Server: Apache/2.2.9 (Debian)
Last-Modified: Sun, 17 Jan 2010 18:17:39 GMT
ETag: "3ba006-29b376-47d60407b56c0"
Accept-Ranges: bytes
Content-Length: 2732918
Content-Type: application/x-gzip

edit2; そして、これは私がファイルを受け取って書き込む方法です:

    memset(file,0,file_size);
    arg[1]=recv(socketfd,file,file_size,0);
    int mstart=0;
    while(file[mstart]!='\n' ||file[mstart+1]!='\r'|| file[mstart+2]!='\n'){
       mstart++;
    }
    mstart+=3;
    fsize=file_size;
    int fsize=file_size-mstart;       //file_size from Response Header
    fwrite(&(file[mstart]),1,fsize,fd);
    fclose(fd)

わかりました、それは非常に理にかなっているので、今これを試しました:(編集)そこに間違いがありますが、これも機能しません:

  fd=fopen(file_name,"wb");  
  memset(file,0,file_size);
  recv(socketfd,file,3,0);
  while(1==1){
    if(file[0]=='\n' ||file[1]=='\r'|| file[2]=='\n'){
      recv(socketfd,file,3,0);
    }else{
      break;
    }
  }
  arg[1]=recv(socketfd,file,file_size,MSG_WAITALL);
  fwrite(file,1,file_size,fd);
  fclose(fd);

しかし、それはまだ動いています

ついに!これはうまくいきます、ありがとう!

  fd=fopen(file_name,"w");  
  memset(file,0,file_size);
  recv(socketfd,file,3,0);
  while(file[0]!='\n' ||file[1]!='\r'|| file[2]!='\n'){
      recv(socketfd,file,3,0);
  }
  arg[1]=recv(socketfd,file,file_size,MSG_WAITALL);
  fwrite(file,1,file_size,fd);
  fclose(fd);
4

1 に答える 1

1

ファイル読み取りロジックがうまく機能しません。最初に固定量を読み取り、その固定量を解析してヘッダーの終わりを見つける必要があります。次に、ヘッダーを解析してコンテンツの長さを見つけます。次に、ヘッダーの終わりを過ぎて既に読み取ったデータは、ファイルの最初の部分として書き出されます。ファイルの残りの部分は、コンテンツの長さから書き込んだ長さを引いたものです。ソケットから読み取ってファイルに書き込む必要があるのは、さらに多くのバイトです。

問題は、コンテンツの長さヘッダー (以前の HEAD リクエストから抽出したもの) を適切に利用していないことです。これは、応答全体の長さではなく、ヘッダーに続く転送のサイズを示します。

ファイルが正しいサイズに見える理由は、正しいバイト数を書き出しているが、ソケットから読み取ったバイトの末尾を超えて読み取っているためです (mstartヘッダーの末尾を超えて前方に調整したため)。

于 2013-05-20T17:00:16.807 に答える