4

c++とを使っTCP/IPて分散システムを書いていsocketsます。

メッセージごとに、着信メッセージの全長を知るために最初の5バイトを受信する必要があります。

これを行うための最良の方法は何ですか?

  1. recv()たった5バイト、それからrecv()また。これを選択した場合、recvで0バイトまたは5バイトを取得すると想定しても安全ですか(試行を続けるためにループを作成しないこともできます)。
  2. 使用するMSG_PEEK
  3. recv()バッファサイズを少し大きくしてから、最初の5バイトを読み取り、最後のバッファを割り当てます。
4

3 に答える 3

4

何も知る必要はありません。TCPはストリームプロトコルであり、いつでも1バイトから数メガバイトのデータを取得できます。TCPソケットを使用する正しい唯一の方法は、ループで読み取ることです。

char buf[4096];        // or whatever

std::deque<char> data;

for (int res ; ; )
{
    res = recv(fd, buf, sizeof buf, MSG_DONTWAIT);

    if (res == -1)
    {
        if (errno == EAGAIN || errno == EWOULDBLOCK)
        {
            break;  // done reading
        }
        else
        {
            // error, break, die
        }
    }
    if (res == 0)
    {
        // socket closed, finalise, break
    }
    else
    {
        data.insert(data.end(), buf, buf + res);
    }
}

ループの唯一の目的は、ソケットバッファからアプリケーションにデータを転送することです。次に、アプリケーションは、ある種の高レベルのアプリケーションメッセージの抽出を試みるのに十分なデータがキューにあるかどうかを個別に判断する必要があります。

たとえば、あなたの場合、キューのサイズが少なくとも5であるかどうかを確認し、最初の5バイトを調べてから、キューが完全なアプリケーションメッセージを保持しているかどうかを確認します。いいえの場合は中止し、はいの場合はメッセージ全体を抽出し、キューの先頭から離れている場合はポップします。

于 2012-09-13T14:49:21.070 に答える
1

2つの状態を持つステートマシンを使用します。

最初の州。

バイトがバッファに到着したときにバイトを受信します。5バイト以上ある場合は、最初の5バイトに対してチェックを実行し、場合によっては残りのバッファーを処理します。2番目の状態に切り替えます。

第二の州。

メッセージの最後に到達したバイトを受信して​​処理します。

于 2012-09-13T14:50:08.233 に答える
0

あなたの質問に具体的に答えるために:

  1. 0または5を取得すると想定するのは安全ではありません。1〜4を取得することも可能です。他の人が示唆しているように、5またはエラーが発生するまでループします。
  2. 私はPEEKを気にしないでしょう。ほとんどの場合、ブロックするか(呼び出しをブロックすると仮定して)、5を取得するので、スタックへの余分な呼び出しをスキップします。
  3. これも問題ありませんが、少しの利益のために複雑さが増します。
于 2012-09-13T17:00:53.037 に答える