18

MUD/MUCK と考えてください。ただし、アバターやロケールのイラストを使用することもできます。私が選んだ言語はruby​​ です。

サーバーとそのさまざまなクライアントの間で非同期に転送されるデータを使用して、複数の永続的な接続を処理する必要があります。クライアント セッションで発生するアクティビティに基づいて、1 つのデータベースを最新の状態に保つ必要があります。各クライアント セッションのアクティビティでは、他の複数のクライアントをすぐに更新する必要がある場合があります (ユーザーがルームに入る、ユーザーが別のユーザーにプライベート メッセージを送信する)。

これは目標プロジェクト であり学習プロジェクトでもあるため、並行ネットワーク プログラミングについてさらに学習するために、車輪を 1 つか 2 つ再発明するつもりです。ただし、私は並行プログラミングとネットワーク プログラミングの両方に不慣れです。以前は、Web アプリでの非永続的な同期 HTTP 要求の世界でほぼ独占的に働いていました。ですから、正しい車輪を再発明していることを確認したいと思います。

embossの優れた回答に従って、特定の HTTP サーバーの内部を調べ始めました。これは、Web アプリは通常、問題がサーバー自体によって完全に抽象化されているため、スレッドの問題を回避できるためです。

私は EventMachine や GServer の機能をまだ理解していないので、使いたくありません。それらがどのように機能するか、どのような問題を解決し、なぜそれらが役立つのかについての一般的な感覚をつかむと、私はそれを快適に感じることができます. ここでの私の目標は、「ゲームを書く」ことではなく、「ゲームを書き、低レベルのもののいくつかがどのように機能するかを学ぶ」ことです。また、特定の用語の境界についても不明です。たとえば、「I/O 非バインド アプリ」は「イベント駆動型アプリ」のスーパーセットですか? 逆に?

もちろん、目標を達成するための正しい方法が存在する場合は興味がありますが、全体として、それが正しい方法である理由と、他の方法があまり好ましくない理由理解したいと考えています。

書籍、電子書籍、オンライン リソース、サンプル プロジェクト、またはその他のちょっとした情報を提案してください。

私が現在行っている方法はIO#select、接続されたソケットのリストをブロックするために使用し、タイムアウトは0.1秒です。読み取った情報をスレッドセーフな読み取りキューにプッシュし、タイムアウトになるたびに、スレッドセーフな書き込みキューからデータをプルします。タイムアウトを短くする必要があるかどうかはわかりません。ソケット処理スレッドの読み取りキューをポーリングし、「要求」を処理する 2 番目のスレッドがあります。これは、最初に動作させた方法よりも優れていますが、それでも理想的ではない可能性があります.

この質問を Hacker News に投稿したところ、私が取り組んでいるいくつかのリソースにリンクされました。似たようなものは何でも素晴らしいでしょう:

4

4 に答える 4

13

おそらく聞きたくないかもしれませんが、最初に HTTP サーバーの調査を開始することをお勧めします。それらのプログラミングは退屈で、同期的で、永続的ではないように見えましたが、それはサーバーの作成者が自分たちの仕事をあなたから非常にうまく隠したからです-考えてみれば、ウェブサーバーはそうではありません同期 (何百万人もの人々がこの投稿を読み終えるまで待たなければならないというわけではありません... 同時実行:) ... そして、これらの獣はとてもうまく仕事をしているからです (ええ、私たちが彼らにたくさん怒鳴っていることは知っていますが、結局のところ、ほとんどの HTTP サーバーは優れたソフトウェアです)。これは、効率的なマルチスレッドについて学びたい場合に検討すべき明確な出発点です。オペレーティング システムやプログラミング言語やゲームの実装も良い情報源ですが、達成しようとしているものとは少しかけ離れているかもしれません。

あなたが本当に指を汚すつもりなら、最初にWEBrickのようなものに慣れることをお勧めします。これは Ruby に同梱されており、Ruby で完全に実装されているため、そこで Ruby スレッドの概念についてすべて学ぶことができます。ただし、 thinなどの C で実装された Web サーバー上にある Rack ソリューションのパフォーマンスに近づくことはできないことに注意してください。

したがって、本当に真剣に取り組みたい場合は、独自のサーバー実装を C(++) で展開し、HTTP をサポートするつもりであれば、おそらくラックをサポートするようにする必要があります。特に最終結果を競争力のあるものにしたい場合は、かなりの作業と言えます。Cコードは非常に高速ですが、非常に遅くなるのも簡単です。それは低レベルのものの性質にあります. また、メモリ管理とセキュリティについてはまだ説明していません。しかし、それが本当にあなたの望みなら、それを実行してください。しかし、私はまず、インスピレーションを得るためによく知られたサーバーの実装を掘り下げます。それらがスレッドでどのように機能するか (プーリング)、および「セッション」をどのように実装するか (持続性が必要でした) を確認してください。必要なことはすべて HTTP で実行できますが、巧妙な REST インターフェイスを使用するとさらに効果的です。あなたが言及したすべての機能をサポートする既存のアプリケーションは、その生きた証拠です。したがって、その方向に進むことは完全に間違っているわけではありません。

それでも独自の独自のプロトコルを発明したい場合は、TCP/IP に基づいて、受け入れ可能な最小の公分母として使用してください。それを超えると、孫がおそらくまだコーディングしているプロジェクトになるでしょう。これは、ネットワーク プログラミングに関して言えば、私が敢えて行うのと同じくらい低い値です。

ライブラリとして使用しているかどうかにかかわらず、EventMachine とその概念モデルを調べてください。旅の中でイベント駆動型 (「ノンブロッキング」) IO を見落とすことは、適切な車輪について学習/再発明するという文脈では怠慢です。Web サーバーとしての node.js の利点を説明する、イベント駆動型プログラミングの前菜。

要件に基づいて: 非同期通信、一元的に発行された「イベント」に反応する複数の「サブスクライバー」。これは、イベント駆動型/メッセージ ベースのアーキテクチャの有力な候補のように思えます。


あなたの旅に役立つかもしれないいくつかの本 (Linux/C のみですが、概念は普遍的です):

(それらは古典でした)


あなたがチェックしたいと思うかもしれないプロジェクト:

  • Apache 2、thin、mongrel、nginx、lighttpd、...、存在する任意の Web サーバー
  • EventMachine (ごめんなさい:)
  • node.js
  • ゲーム内の効率的なネットワーク ( Quake 3 の情報源)
于 2011-07-27T22:18:49.243 に答える
3

ユニコーンの Web サーバー設計について少し読むことをお勧めします。これにより、スレッド対プロセスの議論についての洞察が得られるはずです。

http://unicorn.bogomips.org/DESIGN.html

http://tomayko.com/writings/unicorn-is-unix

于 2011-07-27T21:48:35.230 に答える
2

I don't know much about Ruby - sorry - but I think the architecture needs to be driven by your requirements (motherhood, apple pie...I know).

If you're building something that needs to scale to large numbers of users, your architecture needs to reflect that - and you end up making all sorts of decisions you don't necessarily need to make if you're operating at more modest scale.

Response time also plays a big part - I don't think that is such a big deal with MUD style games, but for web servers or FPS games, it's a huge issue.

Having said that - the only systems similar to what you describe that I know in any detail use an event driven programming model - clients trigger events, the system updates its internal state, and notifies affected clients. The "internal state" is actually stored in a separate application, again communicating using sockets - this allows the app to be scaled by adding more servers to handle client interaction. Not sure you need that level of complexity.

Threading is indeed a real issue, and it creates hard-to-test code, so whilst dash-tom-bang's answer is indeed a little off topic, testability is a significant concern.

于 2011-08-11T13:35:02.520 に答える
-1

正しい方法は、テスト駆動開発を使用することです。次に、発明する必要がある正確な瞬間に、再発明する必要があるものを発見します。

「接続」するテストから開始し、「こんにちは、ユーザー」というメッセージが返されることを表明します。そこから一歩ずつ進んでください。

于 2011-07-27T21:46:55.803 に答える