2

Winsock2ラッパークラス(クライアントサーバー)で問題が発生し、数え切れないほどの混乱の中で頭を悩ませた後、あなたの意見を聞いた方がよいと判断しました。

具体的には、Send()関数を使用するたびに、クライアントとサーバーの両方(常にではありません!)が1バイトまたは2バイト余分に送信するという問題があります。

たとえば、SendBytes( "Hello")を使用すると、Recv関数は文字配列の最後に「•」またはその他のランダムな文字を含む「Hello•」を返します。

    //main.cpp (Client)
    #include "Socket.h"

    int main() 
    {
        NetworkService::Client cService = NetworkService::Client();
        int res = cService.Initialize("127.0.0.1","20248");
        if(res == 0){
            int local = cService.SendBytes("Hello!");
            printf("Bytes Sent: %ld\n", local);
            cService.Shutdown();

            char* temp = cService.Recv();
            printf("String Recieved: %s  - Size: %d",temp,strlen(temp));
            printf("\nSTRLEN: %d",strlen("X5"));
        }
        else{
            cService.Clean();
        }
        cService.Close();
        while(!kbhit());
        return 0;
    }

もちろん、サーバーは文字列「X5」を送信し、クライアントはstrlensを出力します...

//The result with "X5" as the dummy text:  
String Recieved: X5? - Size: 3 //Notice the extra '?' character  
STRLEN: 2

送信//受信機能

    int NetworkService::Client::SendBytes(char* lData){
            int local = send( ConnectSocket, lData, (int)strlen(lData), 0 );
            if (local == SOCKET_ERROR) {
                Close();
                return WSAGetLastError();
            }
            return local;
    }

    char* NetworkService::Client::Recv(){
        recv(ConnectSocket, recvbuf , recvbuflen, 0);
        return recvbuf;
    }

助けていただければ幸いです^_^。

4

3 に答える 3

3

すみませんが、

 int local;
 (...)
 return (int*)local;

何を達成しようとしていたのですか?あなたのコードには多くの深刻な問題があります。

于 2011-09-10T17:41:44.337 に答える
2

これは、ネットワーク経由でデータを送信する方法ではありません。エラーが多すぎます。

ネットワーク経由で null で終わる文字列を送信する場合:

int local = send( ConnectSocket, lData, (int)strlen(lData), 0 );

誰もが言ったように、実際には null ターミネータを送信しません。長さに 1 を加えれば、あなたはそれを送ったでしょう。さらに、長い文字列の場合、send()関数は文字列全体を一度に送信することを保証しません。それを確認して、不足している部分を再送信する必要があります。

recv(ConnectSocket, recvbuf , recvbuflen, 0);

戻り値をチェックしないので、受け取った文字列の長さを知ることはできません。null バイトを送信しないため、受信したデータは null で終了しません。また、ヌル ターミネータが送信するデータの唯一の区切り文字である場合は、いつ終了するかを知るためにヌル ターミネータを見逃さないように、バイト単位で (効率的ではありません) 読み取る必要があります。別の方法としては、独自のバッファリング スキームを作成する (次の読み取りで前の読み取りの結果が部分的に返されるようにする) か、プロトコルを変更して、転送されたデータの長さを事前に知ることができます。また、関数の場合と同様に、部分読み取りについても同じsendことが言えます。

ところで、静的/グローバル バッファーを返すことは、適切なコードの兆候ではありません。

于 2011-09-10T17:53:35.787 に答える
1

の戻り値を実際にチェックすることはありませんrecv

do-while がありますが、何もしません。失敗しても適切なエラー処理なしで関数から戻りrecvますが、それを知ることはありません。

また、必要ではない終了を送信しません。\0これは、何をしようとしているのかによって異なります。たとえば、受信後に追加できます。

于 2011-09-10T17:16:30.257 に答える