現在、C# サーバーと複数の C++ クライアントの間で情報を送信する手段として ZMQ を使用しています。ZMQ は、異なる言語間の標準プロトコルにより、この時点まで完全に機能しました。
しかし、私のプロトコルが進化した今、私は ZMQ で壁にぶつかっています。私のプロトコルでは、送信されたメッセージに正しい RSA キーを適用できるように、現在話しているエンドポイントを知る必要があります。
私がしなければならないことの簡単な概要を説明すると役立つかもしれません。REQ および REP ソケットを使用しています。クライアントは REQ ソケットを使用し、サーバーは REP ソケットを使用します。
- 各クライアントは、socket.connect() を介して tcp 経由でサーバーに接続し、サーバーにその存在を知らせるためにクイック リクエストを送信します。
- サーバーは、ソケットを毎秒ポーリングし、 receiveReady イベントを発生させることでリクエストを受信します。 サーバーは、文字列を介してコマンドを送信することにより、クライアントに秘密/公開キーを生成するように通知します。
- クライアントはこれを行い、公開鍵を文字列を介してサーバーに再度送信します。
- サーバーはキーを取得すると、そのクライアントへのキーとソケットを格納する Client オブジェクトを作成します。(ここでプロトコルが壊れます)。
- 次に、サーバーがクライアントに情報を送信する必要があるときはいつでも、Client オブジェクトをループ処理し、メッセージを暗号化して正しい受信者に送信します。
SocketEventArgs の Socket が、イベントを発生させたエンドポイントにソケットを返すと想定していました。(非 ZMQ C# で接続を受け入れるのと同様) これは間違っているようです。SocketEventArgs のソケットは、すべてのクライアントが接続する「グローバル」ソケットのように見えます。そのため、クライアントが接続するときにソケットを追跡できなくなります。
だから私の質問は、どうすればこれを機能させることができますか? 可能であれば ZMQ を使い続けたいと思っています。ZMQ との連携は非常に素晴らしく、多くの小さなエッジ ケースを解決してくれます。それが不可能な場合、特定のエンドポイントを参照できるようにする ZMQ と同様の別のフレームワークはありますか?
ところで、私は C# 用の clrzmq と共に、3.2.3 である ZMQ の現在の安定版リリースを使用しています。
編集: 考えてみると、1 つの解決策は、各メッセージの前にソケットを識別する文字列を追加することです。現在の実装では、ダウンストリームのクライアントに送信される情報のみが暗号化されます。これは、パケット スニファーを使用している誰かが別のクライアントになりすますことがかなり簡単にできるので、私は心配しています。
EDIT2: このスタック オーバーフローの質問は、私の ZMQ メッセージの発信元の識別に似ています。サーバーに送信するすべてのメッセージを何らかの方法で識別しなければならないという考えをサポートしています。しかし、私の特定のケースでは、IPアドレスなどは気にしません。後でエンドポイントと会話できるように、エンドポイントを保存できるようにしたいだけです。これは、ZMQ では不可能だと思われ始めています。
これは合理的に聞こえますか?
- 各クライアントはサーバーに接続し、サーバーに自分の存在を知らせるためにクイック リクエストを送信します。リクエストには、最初のフレームに追加された一意の ID が含まれています。
- 次に、サーバーはリクエストを確認し、クライアントに秘密/公開キーを生成するように通知します。
- クライアントはこれを行い、公開鍵をサーバーに送信します。
- サーバーがキーを取得すると、キーとクライアントの一意の ID を格納する Client オブジェクトを作成します。
- その後、クライアントは数秒ごとにサーバーをポーリングして新しい情報を取得します。
- サーバーは、送信する新しい情報を受け取るたびに、クライアントがサーバーをポーリングするのを待ってから、ソケットでそのクライアントに応答します。(これが今私が心配していることです。すべてのクライアントが接続する「グローバル」ソケットがメッセージを受信したときに、次に送信するメッセージが同じエンドポイントに送信されるようにするにはどうすればよいですか?)
EDIT3: ソケットの種類を入力するのを忘れたなんて信じられません。私は現在、各クライアントがソケット タイプ REQ で、サーバーが REP ソケットである REQ-REP パターンを使用しています。サーバーはポートにバインドされ、クライアントはそれに直接接続します。クライアントは世界中のどこにでもいる可能性があるため、これはすべて tcp を介して行われます。
EDIT4:元の実装をさらに詳細に更新しました。