0

winsock2libを使用してクライアントからサーバーにファイルを送信しようとしています。

ファイルをchar配列に変換した後、コマンドを使用してこの配列を送信していsend()ます。

問題:別々に送信されたデータ。

例: サイズ: 144429 のファイルがあります。一度に送信するのではなく、データは次のように多くの部分に分割されます: 最初の送信: 1460

2 回目の送信: 21544

3 回目の送信: 57136

等..

データ全体が送信されるまで。

私の質問は次のとおりです。一度ではなく、部分的に送信する原因は何ですか????

解決策は機能していますが、意味がありません:追加している場合

cout << "bla bla bla";

send() 関数の前に、それは機能し、144429 全体を一度に送信します。(ただし、cout に指定した文字列が短い場合は、変更せず、分割して送信します)

コード:

クライアント側

int Client::sendData(char *sendbuf, int length)
{   
    int iResult;

    // if I remove those next few lines (until and including the cout line)
    // the send will split.
    char tmp[1];
    // sent 1 dummy byte
    iResult = send( _connectSocket, tmp, 1, 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        return closeSocket();
    }
    cout << "SENDING DATA..." << endl;

    // THIS IS THE RELEVANT AND ACTUAL DATA I WANT TO SEND
    // send the data
    iResult = send( _connectSocket, sendbuf, length, 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        return closeSocket();
    }

    cout << "Data sent (" << iResult << " Bytes)" << endl;

    return 0;

}

サーバ側:

    char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
int iResult = 0;
int totalBytesRead = 0;

// Receive until the peer shuts down the connection
do {
    totalBytesRead += iResult;
    iResult = recv(_clientSocket, recvbuf, recvbuflen, 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);

// store data into file
FileTransfer::binaryToFile(recvbuf, "doch.docx", totalBytesRead-1);

return 0;

}

4

2 に答える 2

3

send一部のデータを1つのユニットとして送信することを保証する方法はありません。そのように機能しないだけです。システムに「これだけのデータがあります」および/または「これで完了です」と伝えるために、いくつかの追加情報を追加する必要があります。送信側にすべてを1つのパケットで送信するように説得できたとしても、受信側が送信者への単純なケーブルだけで直接接続されていないと仮定すると、パケットが通過中に壊れないことを保証することはできません。ネットワークを介して。

パケットで複数のバイトを送信する場合は、sendを複数回呼び出す必要がある可能性があることを受け入れる必要があります。簡単にするために、任意のサイズの「パケット全体」を取り、必要な回数だけ送信を呼び出す関数を記述します...送信されるデータのサイズを示すプロトコルがある場合(最初の数バイトなど) 、同じことを行う受信機能を持つことができます。

于 2013-03-01T14:44:47.787 に答える
2

使用しているソケット タイプによっては、基になるトランスポート プロトコルのデータ サイズに制限がある場合があります。

ネットワーク ソケットを使用している場合、サイズは最大転送単位によって制限されます ( http://en.wikipedia.org/wiki/Maximum_transmission_unitを参照)。

データがこのサイズに収まらない場合は、エラーが発生するか、すべてのデータが送信されるまで、データの一部を送信するループを繰り返す必要があります。

于 2013-03-01T14:22:22.193 に答える