4

さまざまなエンティティがソケットを介して相互に通信するアプリケーションがあり、C プログラミング言語を使用しています。あるエンティティが別のエンティティに長いメッセージを送信すると、recv() 関数はこのメッセージを部分的に読み取ることがあります。したがって、受信したすべての部分を追加して、受信者側でメッセージを再構築する必要があります。

私の質問は、recv() に関連する一般的なソケット プログラミングの質問です。メッセージが完全に読み取られたことを recv() はどのように認識しますか? 「\n」などの特殊文字でメッセージを終了する必要がありますか? または、メッセージのサイズをヘッダーとして送信する必要がありますか? 一般的な慣行は何ですか?

4

3 に答える 3

7

お気付きのように、ストリーム ソケットにはメッセージ境界の組み込みの概念がありません。メッセージの終わりを判断する何らかの方法をアプリケーション レベルのプロトコルに組み込む必要があります。

あなたが提案したオプションは両方とも共通です:長さのプレフィックス(メッセージの長さで各メッセージを開始する)またはメッセージの終わりの区切り文字(たとえば、テキストベースのプロトコルでは単なる改行である可能性があります) )。あまり使用されない 3 番目のオプションは、各メッセージの固定サイズを義務付けることです。これらのオプションの組み合わせも可能です。たとえば、長さの値を含む固定サイズのヘッダーです。

于 2013-10-28T04:53:48.660 に答える
3

send() と recv() を使用するときは、バッファ サイズを指定します。

このような方法でメッセージを送信する場合:

send(new_socket,message,strlen(message),0);

3 番目のパラメーターは、バッファーのサイズです。

パケットが正常に送信されたかどうかを知る 1 つの方法は、TCP ソケットを使用してsend()おりrecv()、同じ値を返すかどうかです。メッセージのサイズが から返された値と同じかどうかを確認することで、送信側でこれを確認できますsend()

レシーバー側でチェックするには、最も簡単な方法は、文字列の末尾に区切り文字を追加すること\0です。

于 2013-10-28T04:57:58.323 に答える
0

C で大量のネットワーク プログラミングを始めるとすぐに、高水準言語が人気がある理由がすぐにわかります。基本的に、C には多くの機能が組み込まれているため、C にもう少し機能があればいいのにと思います。

まず、ZeroMQ ( http://zeromq.org/bindings:c ) とその C バインディングを確認することを強くお勧めします。これは、接続やメッセージの境界設定などを処理するという点で、おぞましい作業の多くを処理してくれます。すぐに開発でき、すぐに実行できます。これは優れたライブラリの特徴です。

ZeroMQ は、ほぼ完璧なソケット ライブラリです。まだ行っていない唯一のこと(AFAIK)は、接続が崩壊しているかどうかを積極的に監視することです。何かを送信しようとした場合にのみわかります。接続の状態をチェックしたい場合は、独自の接続テスト メッセージを定期的に送信する必要があります。

第二に、シリアル化を検討することをお勧めします。割り当てられたメモリを指す複雑なデータ構造を持ち始めるとすぐに、複雑で難しい領域に入り始めます。この問題に直面したとき、Objective Systems ( http://www.obj-sys.com/index.php )のライブラリとツールを使用して、データ構造を定義およびシリアル化するために ASN.1 を使用することにしました。お金がかかりますし、慣れるまで少し時間がかかりますが、開発時間の節約という点では非常に価値があると思いました。

シリアル化ルーチンと同様に、C が提供しない非常に便利な追加機能を提供します。たとえば、コード ジェネレーターは、データ型をコピーするルーチンを提供します。これは、そのデータ型が、割り当てられたメモリを参照するポインターでいっぱいの構造体である場合に非常に便利です。

無料のツールやライブラリもいくつかあるでしょう。良い代替手段は、C バインディング ( http://code.google.com/p/protobuf-c/ )を持つ Google のプロトコル バッファです。

于 2013-10-28T06:20:43.953 に答える