1

クライアントからサーバーにファイルを送信するための単純なサーバー/クライアント プログラムを作成しています。私はwinsock2を使用しています。毎回データを送信する容量を 5000 に制限しています。

クライアント側 (送信):

int iResult = 0;
int totalBytesSent = 0;

while (length > 0){
    iResult = send( _connectSocket, data, MAX_TRANSIT_SIZE, 0 ); // MAX_TRANSIT_SIZE is 5000
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        return closeSocket();
    }
    totalBytesSent += iResult;
    length -= iResult;
    //cout << "Data sent (" << iResult << " Bytes)" << endl;
}
cout << "Total Bytes Sent: (" << totalBytesSent << ")" << endl;

return 0;

サーバー側 (recv):

    // Receive and send data
char recvbuf[MAX_DATA_SIZE];

int iResult = 0;
int totalBytesRead = 0;

// Receive until the peer shuts down the connection

do {
    totalBytesRead += iResult;
    iResult = recv(_clientSocket, recvbuf, MAX_DATA_SIZE, 0);

    if (iResult > 0) {
        //printf("RECEIVED DATA\n");
        //printf("Bytes received: %d\n", iResult);

    } else if (iResult == 0)
        printf("Connection closing...\n");
    else {
        printf("recv failed: %d\n", WSAGetLastError());
        closesocket(_clientSocket);
        WSACleanup();
        return 1;
    }

} while (iResult > 0);

cout << "Total Bytes Received: (" << totalBytesRead << ")" << endl;

問題:

クライアントとサーバーを実行してファイルを送信した後、送受信された正しいデータサイズ(もちろんファイルサイズはバイト単位)が表示されますが、出力ファイルは異なり、テキストエディター(メモ帳++)で開くと)出力ファイルに含まれるデータが少なく(ただし、ファイル->プロパティは同じファイルサイズを示しています)、一部のデータが重複していることを明確に確認できます。

私の質問:

revc() はどのように機能しますか? 多くの呼び出しでデータを受信して​​いる場合、それはバッファに蓄積されますか? (私の場合:recvbuf)またはバッファを書き換えますか?私が理解している限り、それは蓄積されるので、私のコードは正しいですか??

ありがとう。

4

2 に答える 2

2

コードにいくつかの問題があります。

クライアント側:

send( _connectSocket, data, MAX_TRANSIT_SIZE, 0 );
  • ここでは、すでに送信されたバイトを考慮して更新することはありませんdata。そのため、呼び出すたびsendに同じデータが何度も送信されます (バッファーの最初のMAX_TRANSIT_SIZEバイト)。任意のバイト型 (uint8_t、char、...) へのポインターであるdataと仮定すると、簡単な修正は次のようになります。data

    send( _connectSocket, data + totalBytesSent, MAX_TRANSIT_SIZE, 0 );

  • また、送信するデータ サイズを制限する必要があります。これlengthは、元が の倍数でない限りMAX_TRANSIT_SIZE、データの最後に到達したときにバッファー オーバーランが発生するためです。

    send( _connectSocket, data + totalBytesSent, std::min(length, MAX_TRANSIT_SIZE), 0 );


サーバ側:

recv(_clientSocket, recvbuf, MAX_DATA_SIZE, 0);
  • と同じようにsendrecv「そのバッファで既に受け取ったもの」という概念はありません。したがって、呼び出すたびrecvに、受け取った新しいデータをバッファーの先頭に置き、古いデータを上書きします。これはあなたが望むものかもしれませんし、そうでないかもしれません。そのバッファをどのように使用するかを示していないので、これを伝えるのは難しいです. 受信バッファーを管理するために、送信バッファーについて説明した方法と同じアプローチを使用することをお勧めします。
于 2013-03-02T13:27:49.740 に答える
2

recvbuf のどこに書き込んでいるのかわかりません。recv を呼び出すたびに、すでに recvbuf にあるものを上書きします。したがって、コメントアウトされた「RECEIVED DATA」が出力されている場合は、保持したいデータをバッファからコピーする必要があります。

于 2013-03-02T13:20:05.867 に答える