6

ネットワークを介して 2 人のユーザーが囚人のゲームをプレイできるようにするアプリケーションを設計しようとしています。

ジレンマ ゲーム ( http://en.wikipedia.org/wiki/Prisoner%27s_dilemma )。

基本的に、これには以下が含まれます。

  • ゲーム開始(ラウンド1)。
  • プレイヤー 1 は、協力するか、裏切るかを選択します。
  • プレイヤー 2 は、協力するか、裏切るかを選択します。
  • その後、お互いの決定が表示されます
  • ラウンド2開始
  • 等。

私はいくつかの考えと検索を行いましたが、アプリケーションには次のものが含まれている必要があると思います:

  • 着信 tcp/ip 接続を受け入れるサーバー クラス
  • GUI クライアント (別プログラム)
  • 接続ごとに (最大 2 つ)、サーバーは新しい ConnectedClient クラスを作成します。このクラスには、2 人のプレーヤーのマシン/ID の詳細が含まれます。
  • Server クラスと ConnectedClient クラスは、それぞれにイベントを接続/サブスクライブします。これにより、サーバー命令がプレーヤーに送信される準備ができたとき、またはプレーヤーが入力をサーバーに送信したときなどに、互いにアラートを出すことができます。

最善のアプローチが単一のスレッドを使用して作業を行うことなのか、それともマルチスレッドにすることなのかはわかりません。シングル スレッドの方が明らかに簡単ですが、この状況でそれが可能かどうかはわかりません。TCP/IP 接続を要求する前にアプリケーションを作成したことがなく、2 つの着信接続をリッスンできるかどうかもわかりません。 1 つのスレッド。

次のガイドをオンラインで見つけましたが、2 つのスレッドで 2 つのクライアントを開き、サーバーをバイパスして (ゲーム ロジックを制御する必要があります)、相互に直接通信しているようです: http://www. codeproject.com/Articles/429144/Simple-Instant-Messenger-with-SSL-Encryption-in-Cs

私は非常に興味があり、アプリケーション (主にサーバー クラス) をどのように実装するかについてアドバイスをいただければ幸いです。

私の意図を明確に説明できたことを願っています。前もって感謝します。

4

3 に答える 3

8

私の最初のアドバイスは、ここでは TCP/IP とソケットを忘れることです。その技術スタックで間違いなくそれを行うことができますが、必要なものすべてを実装することは多くの頭痛の種になるでしょう. その理由は、そのようなクラスのタスクにはレベルが低すぎるためです。tcp/ip とソケットを使用するのは、学術的な関心がある場合、または通信を大幅に制御する必要がある場合、または非常に高いパフォーマンス要件がある場合のみです。

したがって、私の 2 番目のアドバイスは、WCF テクノロジを検討することです。以前に使用したことがなくても心配しないでください。それほど難しいことではありません。アプリでソケットを使用する準備ができていれば、WCF を確実に処理できます。あなたのタスクでは、WCF チュートリアルを使用して、最初から 1 ~ 2 時間で基本的なコミュニケーションを作成できます。

したがって、ビジネス ロジックを含むいくつかの API 関数を持つサーバー WCF サービスを作成します。Windows サービス、IIS、またはコンソール アプリケーション内でホストできます。そして、クライアントはその WCF サービスを使用して、プロジェクト内の別のローカル クラスの関数のように関数を呼び出します。WCF は、必要なイベントを実行するのにも役立ちます (ただし、もう少し高度なトピックです)。そして、ここでスレッド化を忘れることさえできます。ほとんどのことは、箱から出してすぐに機能します。

于 2012-11-12T17:54:53.457 に答える
4

まず、他の人が言ったように、ゲーム ロジックをできる限り分離して、基本的な機能が通信インフラストラクチャにあまり依存しないようにします。

通信に関しては、WCF がタスクを処理できます。クライアントが IIS でホストされているサービスにリクエストを送信し、ある種の識別/認証を行い、サービスが結果をプッシュして新しいラウンドの開始を通信できる場所から Duplex チャネルを開くことができます。

1 つのクライアントが接続すると、別のクライアントを待ちます。これが発生すると、デュプレックス チャネル コールバックを使用して最初のクライアントに通知し、その選択を待ちます。次に、2 番目のユーザーに質問し、その応答を待ちます。来ると両方に結果を通知し、ゲームを再開します。

実装をもう少し詳しく説明します。

いくつかの操作 (必要に応じて登録、PushDecision など) を含むサービスが用意されます。また、サービスがクライアントにプッシュする必要がある操作 (NotifyResult、RequestDecision、これらは例です) を使用して、コールバック インターフェイスを定義します。次に、サービス操作にマップするクライアント用のプロキシを作成し、サービスがメッセージをプッシュするときにイベントを公開して発生させる方法でコールバック操作を実装します。

ユースケース:

クライアント A はプロキシを作成し、サーバーで Register を呼び出します。サーバーは呼び出しを受信し、サイレントを登録し、コールバック オブジェクトを状態に保存します。二重接続が確立されます。どういう意味ですか?これは、(PollingDuplexBinding を使用している場合は、おそらくそうするでしょう) クライアント A のプロキシ オブジェクトがサーバーに対して長いポーリング リクエストを実行し、コールバック メッセージがあるかどうかを確認することを意味します。存在しない場合は、再度長いポーリングを行います。存在する場合は、サーバーがプッシュしたデータを渡すプロキシでコールバックのメソッドを呼び出します。プロキシのコールバック メソッドは通常、イベントを発生させるか、デリゲートを実行しますが、選択はユーザー次第です。

クライアント B が接続し (Register を呼び出し)、A に対して行ったのと同じことを行い、サーバーは 2 つのクライアントが接続されていることに気づき、保存されたコールバックを通じて A への応答を要求します。これは、B の Register 呼び出しの処理中に発生する可能性があります。または、B の register 呼び出しで新しいスレッドで実行する (または、 ThreadPoolで実行するか、新しいTaskを開始する) ようにトリガーされる可能性があります。

クライアント A は、その選択を要求するサーバー コールバックを受け取ります。次に、ユーザーに通知し、UI を介して選択を取得できます。サーバーに対して新しい呼び出しが行われます (たとえば、PushDecision)。サーバーはクライアント A の選択を受け取り、B に同じように尋ねます。両方の応答があると、結果を計算し、結果をクライアントにプッシュします。

デュプレックス チャネルを WPF で PollingDuplex と共に使用する利点は、ロング ポーリングを使用するため、80 以外のポートを使用する必要がないことです。

これは決して最終的な実装ではありません。漠然としたアドバイスを提供するのではなく、アイデアを提供するための小さなガイドにすぎません。もちろん、WCF でそれを行う方法は他にもたくさんあるかもしれません。

最初に、アプリケーションが 1 度に 2 人のユーザーしか処理できないと仮定します。その後、別の例として、必要に応じてスケールアップし、アクセスがロックされたマッピング テーブルを使用してサービスを何らかの形式の状態に保つことができます。

WCF に関するいくつかの考え: Visual Studio ツール (svcutil) を使用して WCF で開発を開始する簡単な方法がありますが、私はその方法が好きではありません。WCF インフラストラクチャを十分に "理解" できず、プロキシを生成するための冗長な魔法に縛られ、柔軟性を失います。特に、デュプレックス ポーリングなどの特別なシナリオで使用する必要がある場合はそうです。

もう 1 つの方法は、サービスとプロキシを手動で作成することですが、それほど難しくはありません。それで何ができるかを理解すると、非常に興味深いものになります。それに関連して、1 つのアドバイスを提供できます。プロキシ操作でタスクベースの非同期パターンを使用するようにできる限りのことを行ってください (ここでプロキシ操作を実装するさまざまな方法を確認できます)。これにより、新しい C# のasync/awaitキーワードと組み合わせると、コードがよりクリーンで簡単になり、UI を実装するのが楽しくなります。

開始するためにいくつかのリンクをお勧めします。それらのいくつかは古いものですが、非常に教訓的です。

  • 以前はこのリンクに WCF の素晴らしい記事がありましたが、現在はオフラインになっているようです。幸いなことに、このリンクのファイルで利用可能なコンテンツを見つけました。
  • これは、ホスティングオプションをカバーしています。
  • WCF インフラストラクチャに関するトピック:リンク
  • 両面印刷サービスに関するトピック:リンク リンク リンク
  • タスクベースの非同期パターンに関するトピック:リンク リンク リンク
于 2012-11-21T16:04:31.483 に答える
1

すべてのユーザーがサーバーを介して通信することを主張し、アプリケーションをスケーリングしたい場合に、1 つのアドバイスを与えることができます。

  1. ロジックを分離する (サーバー上に構築するロジックの各部分を理解することによって)

  2. トランザクションごとに複数のユーザーを処理できるようにクラスを作成します

  3. 可能な限り IOCP を使用する

  4. 認証やユーザープロファイルなどが必要な場合は、アプリケーションの構造に依存します..WCFまたはユーザー向けのWebサービスを導入し、バックグラウンドで実際のアクションを非表示にすることができます(これによりパフォーマンスが低下しますが、それが唯一の可能性がありますしたがって、サーバーロジックの上部に認証フレームワークがあり、背後にパイプライン化されたアクションロジックがある場合があります..つまり、ユーザーはサーバーによって提示されたサービスにアクセスできるように認証されますが、これらのサービスすべてのユーザーをパイプライン処理し、できるだけ多くのユーザーを同時に処理します。認証が必要ない場合は、サーバー ロジックと直接通信し、ユーザーの要求に応じて完了ポートを使用できます。ここで多くの作業を行う必要があります。

于 2012-11-21T10:24:41.053 に答える