2

私のサーバーは、サイズが 500kb の 2 つの画像をクライアントに送信する必要があります。クライアントはデータを失うことなく最初の画像を正常に受信しますが、サーバーが他の画像をクライアントに送信すると、サーバーからデータが送信される前に recv() が 0 を返し、その直後にサーバー send() が -1 を返します。 .

これが私の send() と recv() コードです:

サーバ:

    fp2 = fopen(totaldir2,"rb");
if(fp1==NULL)
{
    cout<<"ERROR while openning: "<<totaldir2<<endl;
    getchar();
    exit(1);
}

fseek (fp2, 0 , SEEK_END);
IFileSize2 = ftell (fp2);
rewind (fp2);
picture2 = new char[sizeof(char)*IFileSize2+1];
if (picture2 == NULL) {exit (2);}
itoa (IFileSize2,CFileSize2,10);
countData = 0;
do{
sentData = send(sConnect,CFileSize2,strlen(CFileSize2)+1,NULL);
countData+=sentData;
}while(countData<strlen(CFileSize2)+1);
read = fread_s(picture2, IFileSize2, sizeof(char),IFileSize2, fp2);
countData = 0;
do{
sentData = send(sConnect, picture2, read, 0);
countData += sentData ;
}while(countData<read);

このコードは 2 回実行され、2 つの画像が送信されます。

クライアント:

recv(sConnect, len2, sizeof(len2) ,NULL); \\recv returns 0 here before server sends the data.
FileSize2 = atoi(len2);
picture2 = new char[sizeof(char)*FileSize2+1];
fp2 = fopen("temp\\image2.bin","wb");
if(fp2==NULL)
{
     closesocket(sConnect);
     WSACleanup();
     exit(1);
    }

recv(sConnect, picture2, FileSize2, 0); \\same here
fwrite(picture2, sizeof(char), Received2, fp2);

このコードは 2 回実行され、2 つの画像を受け取ります。

サーバーで send() の後に Sleep() を配置すると、クライアントはすべてのデータとすべての画像を受信しますが、Sleep はクライアント ネットワークに依存します。サーバーは多くのクライアントを取得します。接続は TCP で使用されます。

4

1 に答える 1

1

recv()相手が正常に切断された場合は 0 を返します。TCP はバイト ストリームであることを思い出してください。UDP のようなメッセージの概念はありません。ほとんどの場合、2 番目のイメージは、最初の呼び出しに使用しているのと同じバッファーに格納されています。recv(). ファイル データを送信する前にファイルの長さを送信するなど、データをフレーム化する必要があります。そうすれば、受信者は最初に長さを読み取ってから、長さが示すバイト数だけを読み取ることができます。あなたはそれをやろうとしていますが、うまく管理できていません。まず、可変長文字列を使用してファイルの長さを送信しています。文字列の長さを送信しておらず、受信者は null ターミネータを探していないため、受信者は文字列の長さを認識せず、多くのバイトを読み取る可能性があるため、これはお勧めできません。代わりに、ファイル長を固定長の 4 バイトintまたは 8バイトとして送信する必要があります__int64。これは、受信者にとって非常に読みやすくなります。

于 2012-10-06T18:34:52.647 に答える