3

C++ クライアントと Python サーバー (既に開始済み) との TCP チャットを作成する必要があります。C++ クラスに次のようなメッセージがあります。

class Message{
public:
uint64 utc_time;
uint64 token;
string content;
};

これをクライアントからサーバーに送信しています。サーバーでは、utc_time までに優先キューがあり、他のユーザーにブロードキャストする必要があります。私の質問は、これをシリアル化する方法です。サイズ タイプ size の言語間の依存関係を避けるために、どの形式を使用するのですか? (おそらく将来的にはより多くのメタデータになるので、少し一般的なものが必要です) ? シリアライゼーションに使用するフォーマット(またはバイトのようにのみフラッシュするフォーマット)についてアドバイスをもらえますか?

class Persistent:
public:
    Persistent(int sz):objSize(sz){}
    void write(std::ostream& out)const{out.write((char*)this, objSize);}
    void read(std::istream& in){in.read((char*)this, objSize);}
private:
    int objSize;
};

サーバー上のC ++にデシリアライザーを配置し、可能であればpythonから呼び出すという他の可能性を考えました。この問題に対するエレガントな解決策はありますか?

4

3 に答える 3

4

メッセージの終わりを気にせずにクロス言語とクロスプラットフォームを本当に使いたい場合は、GoogleProtobufZeroMQの組み合わせをご覧ください。

通常のソケットを使用する場合、最初にメッセージのサイズを読み取り(これを先頭に追加します)、次にバイト配列が完全なメッセージである場所から場所までを知ることができます。

protobuf + zmqの使用例:

message Message {
    optional uint64 utc_time = 1;
    required uint64 token = 2;
    optional string content = 3;
}

protobufコンパイラを使用して、C ++コード(またはruby / python / etc)を生成します。

コードで使用するには:

#include <Message.pb.h>

Message msg;
msg.set_token(1);
msg.set_content("Hello world");

zmqを使用して送信するには:

std::string serialized = msg.SerializeAsString();
zmq::message_t reply(serialized.size());
memcpy(reply.data(), serialized.data(), serialized.size());
zmq_socket.send(reply);

zmqを使用して受信するには:

zmq::message_t request;
zmq_socket.recv(&request); // blocking
Message recv_msg;
recv_msg.ParseFromArray(request.data(), request.size());
于 2012-12-05T04:50:09.020 に答える
1

ソケットへの適切なバッファリングされたインターフェイスとストリームに基づく JSON パーサーがあると仮定すると、JSON を使用するのが好きです。JSON の良いところは、各メッセージの長さを指定する必要がないことです。適切に作成された JSON パーサーは、"オブジェクト" の最後にいつ到達したかを知ることができます。そのため、リーダー オブジェクトは JSON をネットワーク経由で解析し、最初のオブジェクトの最後に到達すると、それを 1 つのメッセージとしてシステムに返すことができます。

JSON がデータにとって過剰である場合、常にプレーン テキストが存在します。インターネットのほとんどは、プレーン テキスト (POP、IMAP、HTTP、FTP など) で動作します。それは、プレーン テキストがクロスプラットフォーム/クロス言語を使用するのに最も簡単だからです。

于 2012-12-06T20:45:09.043 に答える
1

ZeroMQ を使用することは、すべてのトランスポート作業を処理してくれるので、良い出発点です。シリアル化する最良の方法は、実行している作業の種類によって異なります。チャット アプリケーションを実行しているので、効率は問題にならないので、自己記述型のテキスト形式を使用します。これは、デバッグ、トレース、ログ、および使用が最も簡単です。protobufs や msgpack のようなものは、測定可能な報酬がないため余分な作業になります。XML、JSON、HTTP スタイルのヘッダー、name=value ペアなどを使用できます。

非常に大量のメッセージ (毎秒数十万) または非常に大きなメッセージ (たとえば 1K バイト以上) を作成するようになると、メッセージ サイズを縮小するさまざまな方法を考え始めることができます。個人的には、パフォーマンスの問題が発生するまではできるだけ単純なテキスト形式を使用し、必要に応じて最も効率的なバイナリ形式に切り替えることをお勧めします。チャットアプリではありませんが...

于 2012-12-06T19:25:21.317 に答える