3

レシーバーでは、私は持っています

recvfd=accept(sockfd,&other_side,&len);
while(1)
{
   recv(recvfd,buf,MAX_BYTES-1,0);
   buf[MAX_BYTES]='\0';
   printf("\n Number %d contents :%s\n",counter,buf);
   counter++;
}

Sender で、私は持っています

send(sockfd,mesg,(size_t)length,0);
send(sockfd,mesg,(size_t)length,0);
send(sockfd,mesg,(size_t)length,0);

MAX_BYTES は 1024 で、mesg の長さは 15 です。現在、recv を呼び出すのは 1 回だけです。対応する送信ごとに recv 関数を 3 回呼び出す必要があります。どうすれば達成できますか?

4

5 に答える 5

5

個別のメッセージをバイト ストリーム プロトコルで送信するには、メッセージをある種のフレーミング言語にエンコードする必要があります。ネットワークはプロトコルを任意のサイズのパケットに分割できるため、受信はメッセージとはまったく相関しません。受信側は、フレームを認識するステート マシンを実装する必要があります。

単純なフレーミング プロトコルは、長さフィールドを持つことです (たとえば、2 オクテット: 16 ビットで、最大フレーム長は 65535 バイトです)。長さフィールドの後には、正確にその数のバイトが続きます。

長さフィールド自体が一度にすべて受信されると想定してはいけません。2 バイトを要求しても、1 バイトrecvしか返されない場合があります。これは、ソケットから受信した最初のメッセージでは発生しません。これは、ネットワーク (またはローカル IPC パイプ) セグメントが 1 バイトだけの長さではないためです。しかし、ストリームの途中で、16 ビット長フィールドの最初のバイトが 1 つのネットワーク フレームの最後の位置に到達する可能性があります。

これに対処する簡単な方法は、未加工のオペレーティング システム ファイル ハンドルの代わりにバッファ付き I/O ライブラリを使用することです。POSIX 環境では、開いているソケット ハンドルを取得し、関数を使用してそれをストリームfdopenに関連付けることができます。次に、 やのFILE *ような関数を使用して、入力処理を (ある程度) 簡素化できます。getcfread

インバンド フレーミングが受け入れられない場合は、フレーミングをサポートするプロトコル、つまりデータグラム タイプのソケットを使用する必要があります。これの主な欠点は、IP で使用される主要なデータグラム ベースのプロトコルが UDP であり、UDP が信頼できないことです。これにより、順序が乱れたフレームや欠落したフレームに対処するために、アプリケーションが非常に複雑になります。フレームのサイズは、すべてのプロトコル ヘッダーを含めて約 64 キロバイトの最大 IP データグラム サイズによっても制限されます。

大規模な UDP データグラムは断片化されます。ネットワークに信頼性がない場合、さらに信頼性が低下します。IP フラグメントが失われると、パケット全体が失われます。そのすべてを再送信する必要があります。失われたフラグメントの繰り返しを取得する方法はありません。TCP プロトコルは「パス MTU 発見」を実行してセグメント サイズを調整し、IP フラグメンテーションが回避されるようにします。また、TCP は欠落したセグメントを回復するための選択的再送信を行います。

于 2013-06-07T19:16:58.680 に答える
0

最初に、これを送信するために使用するバイト単位lengthのサイズに関する固定形式で受信する を送信し、バイトが受信されるまでループします。lengthlengthrecv()length


(他の回答でもすでに述べたように)受信したチャンクのサイズと数は、送信したものと必ずしも同じである必要はないことに注意してください。受信したすべてのバイトの合計のみが、送信したすべてのバイトの合計と同じになります。

recvおよびのマニュアル ページを参照してsendください。特に、これらの関数RETURNに関するセクションを読んでください。

于 2013-06-08T08:02:13.173 に答える