2009-07-21 13 views
4

TCP/IP接続を介して送信する必要がある一連のメッセージがある状況が続いています。私は決してメッセージクラスの設計のための良い解決策を見つけたことはありません。私はすべてのメッセージがそこから派生するメッセージベースクラスを持っていたいと思います。各メッセージは異なるフィールドを持つため、メンバー変数やメソッドを使用してフィールドにアクセスすることができます。何かのように...TCP/IP接続を介したストリーミング

このようにして、私はmessage_controlを作成して、それに割り当てたり読んだりするアクションメンバーにアクセスできます。あまりにも多くのコードを書くことなく、メッセージを渡すこともできます。

メッセージを送信する必要があるときに問題が発生します。私が演算子< <と演算子>>を上書きすると、一度に1つの変数にメッセージを送ることができます。その解決策の問題は、データを送信するために非常に多くの呼び出しを行うと、コンテキストスイッチがプロセッサをスラムすることにあります。また、ストリーミングオペレータは、ソケットクラスを終了し、私がそれが好きなメッセージクラスには終わりません。

socket& socket::operator<<(message_control& message) 
{ 
    sock << type; 
    sock << action; 
} 

私は、バッファにデータをパックした場合、私はCの領域に離れてC++などから取得し、私自身はポインタの寛大な使用することなどがわかります。コードを変更するのは難しく、エラーが発生しやすいです。また、ストリーミング演算子はまだメッセージクラスではなくソケットクラスにあります。

socket& socket::operator<<(message_control& message) 
{ 
    byte* buffer = new byte[sizeof(message.type) + sizeof(message.action)]; 

    memcpy(buffer, message.type, sizeof(message.type)); 
    memcpy(buffer + sizeof(message.type), message.action, sizeof(message.action)); 

    sock.send(buffer); 
} 

最後に中間クラスを使用して、バッファ内のメンバーのパッキングとアンパックを処理しました。メッセージは演算子< <を実装し、演算子>>をバッファクラスに実装し、バッファクラスをソケットに送信することができます。これはうまくいくが、うまくいかない。

class socket 
{ 
    public: 
    socket(); 
    ~socket(); 

    socket& operator<<(buffer& buff); 
}; 

class buffer 
{ 
    public: 
    buffer() {m_buffer = new byte[initial_size];} 
    ~buffer() {delete [] m_buffer;} 

    buffer& operator<<(unsigned int value); 

    private: 
    byte* m_buffer; 
}; 

void message_control::serialize(buffer& buff) 
{ 
    buff << type; 
    buff << action; 
} 

私はこの問題に対する洗練された解決策があるとは感じられません。私は達成しようとしているものに合ったデザインパターンを見つけることができません。誰もがこの問題を経験し、あなたが良い古いポインタとバイトの配列でより良くなるように感じさせないような設計を思いついたことがありますか?

更新

私は、私が最も頻繁に非常によくワイヤプロトコルを定義して取り扱っております、私のオリジナルのポストに言及しませんでした。そのため、私は通常自分のソリューションをロールバックする必要があり、ネットワーク接続を介してメッセージングに利用できるすばらしいツールキットを使用することはできません。

+0

あなたはACEを使用して見たことがありますか? – Alan

+0

あまり役に立ちませんので、ちょうどそのコメントです。しかし、私はあなたの最後のパターンとほぼ同じパターンを実装しました。私の場合を除いて、バッファは少しだけ正当化されました。私はそれぞれのメッセージの横にある程度大きな構造を持っていました。バッファはとても役に立ち、私の心の中では適切でした。それにもかかわらず、それは私のためにうまくいく、と私は大きなデータを渡していない場合でも同じように動作します! – DeusAduro

+0

DeusAduro - 私はまた、これを大きな(100 KBの)メッセージと共に使用する必要がありました。バッファークラスが非常にスレッド化された環境でうまく動作するようになると、作業がはるかに簡単になりました。私はそれが最良の解決策であることを発見した、そして私は唯一ではないことを嬉しく思います。 –

答えて

1

"このソリューションの問題は、データを送信するために非常に多くの呼び出しを行うと、コンテキストスイッチがプロセッサをスラングすることです。また、ストリーミングオペレータはソケットクラスを終了し、私が好むメッセージクラスではありません住んでいました。"

2番目の問題を解決するには、ソケットクラスのメンバ関数ではなく、メッセージクラスを含む名前空間に非メンバ関数としてoperator<<を定義します。 ADLはそれを見つけるでしょう。

最初の問題の解決策は、プロセス内のデータをバッファし、各メッセージの最後にフラッシュすることです。 Nagleのバッファリングがコンテキストスイッチを妨げていないなら、ソケットをつぶすことでこれを達成できるかもしれませんが、わかりません。あなたが確かにできることは、より多くのC++ - ishの方法で送る前に各メッセージを準備することです。置き換え:

sock << type; 
sock << action; 

で:

stringstream ss; 
ss << type; 
ss << action; 
sock << ss.str(); 
関連する問題