2017-06-02 18 views
0

サーバーからクライアントにファイルを転送するプログラムを実装したいと考えています。私はデータの読み書きに読み書き機能を使用しなければなりません。ここにサーバーとクライアントのコードを示します。ソケットを介してファイルを転送する

server.c

char buffer[512];   

    if((file = open(strTable[1], O_RDONLY)) == -1) { perror("Open"); } 

    while(read(file, buffer, sizeof(buffer)) != 0) 
    { 
     size = strlen(buffer)+1; 
     if(write(newsock, &size, sizeof(size)) < 0) { perror("Write"); exit(1); } 

     write_all(newsock, buffer, strlen(buffer)+1); 
    } 

    size = 4; 
    if(write(newsock, &size, sizeof(size)) < 0) { perror("Write"); exit(1); } 
    write_all(newsock, "end", 4); 

これ開きstrTable [1](私は読んしたいファイルが含まれている)、それははsizeof(バッファ)バイトを読み込み、私はどのくらいのバイト私はクライアントに送信ソケットに書き込み、その後バイトを送信します。ここにwrite_all関数があります。

int write_all(int sock, char* buffer, int size) 
{ 
    int nwrite, sent = 0; 

    while(sent < size) 
    { 
     if((nwrite = write(sock, buffer + sent, size - sent)) < 0) 
     { perror("Write"); exit(1); } 

     sent += nwrite; 
    } 

    return sent; 
} 

いるclient.cは

if((file = open(absolute, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) 
       { perror("Open"); }  

while(true) 
     { 
      received = 0; 

      /* Read the desired readable size */ 
      if(read(sock, &size, sizeof(size)) < 0) 
      { perror("Read"); pthread_exit(NULL); } 

      /* Read all data */ 
      while(received < size) 
      { 
       if((nread = read(sock, buffer + received, size - received)) < 0) 
       { perror("Read"); pthread_exit(NULL); } 

       received += nread; 
      } 

      if(strncmp(buffer, "end", 4) == 0) { break; } 

      write_all(file, buffer, strlen(buffer)+1); 
     } 

クライアントファイル(絶対)を開き、それを読み込む何それに書き込みます。それは最初にどのくらいの大きさの読み込みが必要なのかを読み取ってから、そのサイズに達するまで読み込みを停止します。クライアントが "end"を読み取ると、サーバーはソケットへの書き込みを停止して、クライアントが読み取りを停止します。

問題は、転送後にファイルを開くことができないということです。私は開いていないいくつかの画像を読んでいます。私はまた、いくつかのランダムな言葉を書く1つのfile.txtを読んで、これはコピーされているようだが、それはあまりにも(その写真番号2)いくつかのゴミを持っています。なぜ私はこれを取得し、どのように私はソケットからファイルを正しく転送できますか?

enter image description here

enter image description here

+0

[タグ:エンコーディング]の関連性が私を逃れます。 – EJP

+0

'read'と' write'はどちらも、読み書きされたバイト数のカウントを返します。要求されたバイト数より少なくなる可能性があります。 –

答えて

1

通常の問題。 read()はバッファをNULL終端しないので、カウントとしてcountが有効でないため、strlen()を使用してください。読み取り/書き込みループは次のようになります。

次のようにエラー処理が続く
int count; 
while ((count = read(inFD, buffer, sizeof buffer)) > 0) 
{ 
    if (write(outFD, buffer, count) < 0) 
    { 
     perrror("write"); // at least 
     break; 
    } 
} 

if (count < 0) 
{ 
    perror("read"); // at least 
} 

あなたの第二の問題は、"end"が別々のメッセージとして自身によって受信されることを想定しています。これを保証するものではありません。各ファイルの後にソケットを閉じることによってストリームの終わりを使用するか、または各ファイルより先に長さを送信し、各ファイルのストリームからそのバイト数だけ正確に読み取る必要があります。しかし、すでに長さを送っているので、とにかく"end"を送るのは意味がありません。

+0

また、 'write'の戻り値をチェックする必要があります。これは、' count'バイトより少ないバイトしか書き込めない場合があります。この場合、さらに書き込みを行うには別の書き込み呼び出しが必要です。 –

+0

特に非ブロッキングモードです。いくつかの特定の基礎をなすオブジェクト(パイプやファイルなど)は、特定の制限値以下の書き込みは短い値を返すことはないが、その数が実際にはその制限値よりも小さく、outFDが制限値が適用される値であることを確認する必要がある... –

+0

@ChrisDodd申し訳ありませんが、私は誤って話しました。 Posixの仕様では* blocking *モードではありませんが、確かにエラーをチェックしておく必要があります。 – EJP

関連する問題