0

これはクライアントコードのスニペットです。

connect(DescrittoreClient, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

strcpy(Buffer, filename);

send(DescrittoreClient, Buffer, strlen(Buffer), 0);
fd = open(filename, O_CREAT | O_WRONLY,0644);

while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) != 0) {
    write(fd, Buffer, nread);
    memset(Buffer,0,sizeof(Buffer));
}
int gg;
while( (gg = recv(DescrittoreClient, Buffer, sizeof(Buffer), 0)) == -1) continue;
printf("%d\n", gg);
printf("Risposta del server: %s\n", Buffer);

close(DescrittoreClient);
return EXIT_SUCCESS;

そして、これはサーバーコードのスニペットです。

while(1){

    rc = recv(DescrittoreClient, filename, sizeof(filename), 0);

    fd = open(filename, O_RDONLY);

    fstat(fd, &stat_buf);

    offset = 0;
    rc = sendfile(DescrittoreClient, fd, &offset, stat_buf.st_size);
    if (rc != stat_buf.st_size) {
        fprintf(stderr, "incomplete transfer from sendfile: %d of %d bytes\n", rc, (int)stat_buf.st_size);
        exit(1);
    }
    strcpy(Buffer, "Dati inviati correttamente");
    if( (send(DescrittoreClient, Buffer, strlen(Buffer), 0)) == -1){
        printf("Errore nell'invio della stringa\n");
        close(DescrittoreClient);
        close(fd);
        exit(1);
    }

}
close(DescrittoreServer);
return EXIT_SUCCESS;

これは予想される動作です。

Client --Give me file X--> Server
Server --send the file X--> Client
Server -->send string "File has been sent"--> Client

しかし、これは実際の動作です。

Client --Give me file X--> Server
Server --send the file X--> Client
Server -->_NOTHING_--> Client

問題は、クライアントが「ファイルが送信されました」を受信しないことです。問題がサーバー側にあるかどうかを確認しましたが、そうではありません(実際にはサーバーが文字列を送信します)

4

1 に答える 1

2

(上記のコメントに基づいて) -- 認識すべきことは、TCP 通信が 100% ストリーム ベースであり、組み込みのフレーミングがないことです。つまり、TCP 層が行うことはすべて、送信者が送信したのと同じ順序で受信者がバイトを受信することを確認することですが、バイトが送信されたのと同じ間隔で受信されることを保証するものではありません。(たとえば、send() で 10 バイト、次に 20 バイト、次に 50 バイトの場合、受信側は 80 バイトすべてを一度に受信するか、63 バイトに続いて 17 バイトを受信するか、合計が合計 80 バイト)。

したがって、受信者がそれらを正しく解釈できるように複数の個別のアイテムを送信するには、データをフレーミングするための独自のルールを定義する必要があります。あなたの場合、nバイトのファイルデータを送信し、その後に文字列を送信する必要があります.受信プログラムが知る必要があるのは、予想されるファイルデータのバイト数です。そうすれば、(その数の)バイトを受信すると、残りのバイトが文字列データであることがわかり、ファイルに書き込むだけではありません。

私の提案は、最初にファイルのサイズを送信することです (4 バイトの整数、または 4 ギガバイトを超えるファイル サイズをサポートする必要がある場合は 8 バイトの長さ)。次に、受信コードは次のようになります。

  1. 4バイト受信
  2. これらの 4 バイトを整数として解釈します (この値を、送信側では htonl() を介して、受信側では ntohl() を介して渡し、ここで発生する可能性のあるエンディアンの問題を回避することができます)。
  3. N バイトを受信して​​ファイルに書き込む
  4. 残りのバイトを文字列として受け取ります。
于 2012-06-18T16:07:29.787 に答える