2016-11-29 5 views
0

現在、C++ for Linuxでソケットラッパーを作成中です。基本的には、TCPソケットの作成、接続、送信、読み取り、および終了を処理するクラスのコレクションです。C++ソケットは最初の4バイトのデータのみを送信します

私のソケットクラスでは、send関数とreceive関数以外のすべての関数がうまく機能します。彼らはエラーを返さない。代わりに、最初の4バイトのデータのみを送信します。

マイ送信機能:その背後にある

int Socket::sends(char* buffer){ 

    int bytes; // for number of bytes sent 

    /* First, send the size of buffer */ 
    int datalen = strlen(buffer); // get sizeof buffer 
    int len  = htonl(datalen); // reformat 

    // send the size of the buffer 
    bytes = send(socketfd, (char*)&len, sizeof(len), 0); // send the size 
    if (bytes < 0){ 
     cerr << "Error sending size of buffer to socket" << endl; 
     return 1; 
    } 

    /* Now acutally send the data */ 

    bytes = send(socketfd, buffer, datalen, 0); 
    if (bytes < 0){ 
     cerr << "Error writing buffer to socket" << endl; 
     return 1; 
    } 

    cout << bytes << " written" << endl; 

    return 0; 

} 

アイデアは、それが最初のバッファのサイズを送信した後、実際のバッファを送信することにより、バッファ(char* buffer)を送ることです。エラーが発生した場合(帰国-1)関数は今1

を返すことによって終了し、ここでの読み取り方法は次のとおりです。ここで

int Socket::reads(char* buffer){ 

    int bytes, buflen; // for bytes written and size of buffer 

    /* Read the incoming size */ 
    bytes = recv(socketfd, (char*)&buflen, sizeof(buflen), 0); 
    if (bytes < 0){ 
     cerr << "Error reading size of data" << endl; 
     return 1; 
    } 
    buflen = ntohl(buflen); 

    /* Read the data */ 

    bytes = recv(socketfd, buffer, buflen, 0); 
    if (bytes < 0){ 
     cerr << "Error reading data" << endl; 
     return 1; 
    } 

    return 0; 
} 

、アイデアは、最初のデータのサイズを読み取ることで、バッファをそのサイズに設定して読み込みます。関数はエラー時に1を返します(recvは-1を返します)。メソッドを使用して

は次のようになります。

socket.sends("Hello World"); // socket object sends the message 

char* buffer; 
socket.reads(buffer); // reads into the buffer 

しかし、私はこれらの関数を使用し、これまで、私は奇妙な、非ASCII文字に続いて、データの最初の4つのバイトを受信したとき。なぜこのようなことが起こるのか分かりません。 sendrecv関数でエラーは発生せず、関数は4バイトしか書き込まれていないと言っています。データを送受信する方がいいですか?私は非常に単純なエラーを見落としていますか?

ありがとうございました!

+1

をしてください避けるためにstd::stringまたはstd::vector<char>で行うことができます。関連するタグのみを使用してください。 – kaylum

+2

読み取りに十分なメモリが割り当てられていることをどのように知っていますか?サンプルコードは 'buffer'という名前のポインタを作成しますが、割り当てられたメモリを指しません。 –

+1

ブロックされていないソケットを使用している場合、 'recv'は0を含む任意のバイト数を読み込みます。すべてのデータがあるかエラーが返されるまで' recv'を呼び出す必要があります。 – alain

答えて

4

readsメソッドに初期化されていないポインタ(buffer)が渡されている可能性がありますが、これはおそらく部分的に動作することを示しています(未定義の動作)。

そして、それは変更されません(とあなたはまだ、とにかくサイズがわからない)ので、あなたは、パラメータとしてbufferを渡すべきではありません

プラス、あなたが受け取るとき、あなたのメッセージを、NULLで終了する必要がありますそれ。

私はこのように行うだろう:

char *Socket::reads(){ 
    char* buffer; 
    int bytes, buflen; // for bytes written and size of buffer 

    /* Read the incoming size */ 
    bytes = recv(socketfd, (char*)&buflen, sizeof(buflen), 0); 
    if (bytes < 0){ 
     cerr << "Error reading size of data" << endl; 
     return 1; 
    } 
    buflen = ntohl(buflen); 
    buffer = new char[buflen+1]; // +1 for the NUL-terminator 
    /* Read the data */ 

    bytes = recv(socketfd, buffer, buflen, 0); 
    if (bytes < 0){ 
     cerr << "Error reading data" << endl; 
     return 1; 
    } 
    buffer[buflen] = '\0'; // NUL-terminate the string 

    return buffer; 
} 

をメイン:

socket.sends("Hello World"); // socket object sends the message 

char* buffer = socket.reads(); // reads into the buffer 

delete []に最後のバッファを忘れないでください

もCおよびC++は、さまざまな言語であることに注意newdelete

+0

これは良いアドバイスですが、OPの 'buffer'が十分大きければ、UBはありません。初期化されていないわけではなく、おそらく割り当てられてから関数に渡されます。 – alain

+0

あなたは正しいかもしれません。たぶん私は確かに早すぎると答えました。私はヌル終端部分は確信しています。バッファが十分な大きさであっても、送信されていないために終了しないと、ゴミが出ます。 –

+0

OPの最後のコードで 'socket.reads(buffer);'が起きたとき、 'buffer'は明らかに初期化されません。 –

関連する問題