0

Windows で Winsock2 を使用してネットワーク経由でデータを受信するのに問題があります。シンプルなクライアントとサーバー システムを使用して、ファイル転送プログラムを実装しようとしています。現在のコードでは、バッファのサイズではないため、最後に受信したパケットはファイルに追加されません。そのため、ファイル転送は完全には完了せず、エラーが発生して中断します。常に最後のパケットではなく、それより前の場合もあります。

サーバー コードのスニペットを次に示します。

int iResult;
ifstream sendFile(path,  ifstream::binary);
char* buf;

if (sendFile.is_open()) {
printf("File Opened!\n");
// Sends the file
while (sendFile.good()) {
    buf = new char[1024];
    sendFile.read(buf, 1024);
    iResult = send(AcceptSocket, buf, (int)strlen(buf)-4, 0 );
    if (iResult == SOCKET_ERROR) {
        wprintf(L"send failed with error: %d\n", WSAGetLastError());
        closesocket(AcceptSocket);
        WSACleanup();
        return 1;
    }
    //printf("Bytes Sent: %d\n", iResult);
}
sendFile.close();

}

クライアント コードのスニペットは次のとおりです。

int iResult;
int recvbuflen = DEFAULT_BUFLEN;
char recvbuf[DEFAULT_BUFLEN] = "";

do {
    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    if ( iResult > 0){
        printf("%s",recvbuf);
        myfile.write(recvbuf, iResult);
    }
    else if ( iResult == 0 ) {
        wprintf(L"Connection closed\n");
    } else {
        wprintf(L"recv failed with error: %d\n", WSAGetLastError());
    }

} while( iResult > 0 );

myfile.close();

辞書であるファイルを転送しようとすると、ランダムに壊れることがあります。たとえば、ある実行は S の早い段階で壊れ、末尾に奇妙な文字が追加されましたが、これは珍しいことではありません。

...
sayable
sayer
sayers
sayest
sayid
sayids
saying
sayings
╠╠╠╠╠╠╠╠recv failed with error: 10054

これらのエラーや奇妙な文字を処理するにはどうすればよいですか?

4

2 に答える 2

0

エラーはサーバー側で発生しています。「ピアによる接続のリセット」エラーが発生します。

この行buf = new char[1024];---は明らかに問題があり、メモリが不足しているためにサーバーがクラッシュする可能性があります。クリーンアップは行われません。適切なステートメントを追加することから始めます。deleteおそらく、send呼び出しの後に配置するのが最適です。それでも問題が解決しない場合は、小さなテストファイルを使用して、サーバーコードのwhileループを実行します。

PSループ内で使用するよりも優れた解決策は、既存のバフを再利用することnewです。deleteコンパイラはこの間違いを最適化する可能性がありますが、そうでない場合は、アプリケーションのパフォーマンスを大幅に妨げています。buf = new char[1024];実際には、ループの外側に移動する必要があると思います。bufはcharポインタなので、渡すとread内容が上書きされ続けます。バッファを何度も再割り当てするのは良くありません。bufbuf

エラーに関してMSDNは次のように述べています。

既存の接続は、リモートホストによって強制的に閉じられました。これは通常、リモートホスト上のピアアプリケーションが突然停止した場合、ホストが再起動された場合、ホストまたはリモートネットワークインターフェイスが無効になっている場合、またはリモートホストがハードクローズを使用した場合に発生します(リモートのSO_LINGERオプションの詳細については、setsockoptを参照してください)。ソケット)。このエラーは、1つ以上の操作の進行中にキープアライブアクティビティが障害を検出したために接続が切断された場合にも発生する可能性があります。進行中の操作はWSAENETRESETで失敗します。後続の操作はWSAECONNRESETで失敗します。

于 2013-03-02T20:40:28.347 に答える
-1

First, using the new operator in a loop might not be good, especially without a corresponding delete. I'm not a C++ expert, though (only C) but I think it is worth checking.

Second, socket error 10054 is "connection reset by peer" which tells me that the server is not performing what is called a graceful close on the socket. With a graceful close, WinSock will wait until all pending data has been received by the other side before sending the FIN message that breaks the connection. It is likely that your server is is just closing immediately after the final buffer is given to WinSock without any time for it to get transmitted. You'll want to look into the SO_LINGER socket options -- they explain the graceful vs non-graceful closes.

Simply put, you either need to add your own protocol to the connection so that the client can acknowledge receipt of the final data block, or the server side needs to call setsocketopt() to set a SO_LINGER timeout so that WinSock will wait for the TCP/IP acknowledgement from the client side for the final block of data before issuing the socket close across the network. If you don't do at least ONE of those things, then this problem will occur.

There's also another article about that here that you might want to look at:

socket error 10054

Good luck!

于 2013-03-02T20:41:43.153 に答える