UDPノンブロッキングまたは受信用の別のスレッド?


10

マルチプレイヤーゲーム(64歳未満のプレイヤー向け)を作成しています。私はすでにネットワークループ用に別のスレッドを用意することを決めましたが、UDPを受信するための追加のスレッドを作成するのか、受信用ソケットを非ブロッキングに設定する(追加のスレッドなしで)のが良いのか疑問に思っていました。

または、非同期ソケットのような別の方法を使用する方が良いですか?より良い方法はいつでも歓迎です!

回答:


6

さて、まず第一に、何かがあり、それが機能している場合、通常はそのままにしておくことをお勧めします。壊れていないものを修正するのはなぜですか?

しかし、問題があり、実際にネットワークコードを書き直したい場合は、主に4つの選択肢があると思います。

  1. マルチスレッドブロックコード(現在実行していること)
  2. レベルトリガー通知のある非ブロッキングソケット
  3. 準備変更通知を伴う非ブロッキングソケット
  4. 非同期ソケット

多くのマルチプレーヤー(ピアツーピアから大規模マルチプレーヤーまで)のクライアントとサーバーを作成したので、オプション2を使用すると、サーバーとクライアントの両方のゲーム部分で、複雑さが最小限になり、パフォーマンスがかなり向上すると思います。間もなく、オプション4を使用しますが、通常はプログラム全体を再考する必要があります。ほとんどの場合、クライアントではなくサーバーで使用すると便利です。

特に、マルチスレッド環境でソケットをブロックすることはお勧めしません。そうすると、通常、ロックやその他の同期機能が発生し、コードの複雑さが大幅に増加するだけでなく、一部のスレッドが待機するため、パフォーマンスが低下する可能性があります。その他。

しかし、何よりも、ほとんどのソケット実装(およびその時点でのほとんどのI / O実装)は、最低レベルで非ブロッキングです。ブロッキング操作は、単純なプログラムの開発を単純化するために提供されているだけです。ソケットがブロックしているとき、そのスレッドのCPUは完全にアイドル状態になっているので、すでに非ブロック化タスクの上にブロック化抽象化の上に非ブロック化抽象化を構築するのはなぜですか?

ノンブロッキングソケットプログラミングは、試していないと少し気が遠くなるかもしれませんが、非常に簡単で、すでに入力ポーリングを実行している場合は、ノンブロッキングソケットを実行するという考え方を持っています。

最初に行うことは、ソケットを非ブロッキングに設定することです。あなたはそれをしfcntl()ます。

その後、あなたが行う前にsend()recv()sendto()recvfrom()accept()connect()少し異なっている)、またはスレッドをブロックすることができ、他の呼び出し、お電話select()ソケットに。select()後続の読み取りまたは書き込み操作を、ブロックせずにソケットで実行できるかどうかを示します。その場合は、必要な操作を安全に行うことができ、ソケットはブロックしません。

これをゲームに含めるのは非常に簡単です。たとえば、次のようなゲームループが既にある場合:

while game_is_running do
    poll_input()
    update_world()
    do_sounds()
    draw_world()
end

次のように変更できます。

while game_is_running do
    poll_input()
    read_network()
    update_world()
    do_sounds()
    write_network()
    draw_world()
end

どこ

function read_network()
    while select(socket, READ) do
        game.net_input.enqueue(recv(socket))
    end
end

そして

function write_network()
    while not game.net_output.empty and select(socket, WRITE) do
        send(socket, game.net_output.dequeue())
    end
end

リソースの面では、本棚に1冊しかないと思う本は、亡くなったRichard Stevensによる「Unix Network Programming、Vol 1」だけです。Windowsや他のOS、言語ソケットのプログラミングを行うかどうかは関係ありません。この本を読むまで、ソケットを理解しているとは思わないでください。

マルチソケットプログラミング(主にサーバープログラミングに関連)に関して利用可能なソリューションの一般的な概要を見つけることができるもう1つのリソースは、このページです。


ゲームエンジンを開始したばかりなので、書き換えは問題になりません。この回答は本当に役に立ち、本の推薦に感謝します。ゲームのネットワーキングについてより具体的な本も知っていますか?
Yannick Lange

3
@YannickLange:いいえ。ただし、ネットワーキングはジャンルにとらわれないため、ゲーム固有の本を探すことはお勧めしません。また、Stevensの本に匹敵する本は他にありません。ただし、メッセージ指向のプログラム(ほとんどのゲームと同様)を作成する場合は、メッセージ指向のプロトコルを使用することをお勧めします。多くの人は、TCPを介してメッセージ抽象化を作成する傾向があります。TCPは、それ自体がメッセージ指向プロトコル(IP)を介して構築されたストリーム指向抽象化です。
パンダパジャマ2013年

-1

使用しているプログラミング言語を記述していませんが、ほとんどの言語は、基盤となるオペレーティングシステムの機能を利用することが多い、優れた非同期ソケットフレームワークを提供しています。

ブロッキングソケットに基づいて独自のスレッド化された実装を作成する場合(複数のクライアントがある場合は、すべての単一ソケットにスレッドが必要です)、非同期ソケットフレームワークがすでに提供しているものを再発明します。

したがって、非同期ソケットを使用することをお勧めします。


4
なぜ彼はすべてのソケットにスレッドが必要なのですか?特に非同期ソケットでは?多くのヘビー級サーバーは「スレッドプール」モデルを使用してソケットデータを処理します。各スレッドはN個のクライアントにサービスを提供し、必要に応じてスポーンまたは強制終了されます。ただ、この答えは改善が必要だと思います:D
グリムショー

@グリムショウ私の答えを誤解したと思います。ブロッキングソケットを使用する場合は、マルチスレッドモデルが必要になることを明確にしたと思います。
Philipp

@Philipp使用しているプログラミング言語はわかりませんでした。なぜなら、それは質問にはあまり関係がないと思ったからです(ところで、C ++を使用しています)。非同期ソケットの使用をお勧めします。ゲーム(エンジン)でこれらのタイプのメソッドを学習するために推奨される本/ウェブページを知っていますか?
Yannick Lange

@Grimshaw:各スレッドはどのようにNクライアントにサービスを提供していますか?ブロックしていて、残りのソケットの状態に関係なく、各ソケットのデータが処理されるようにするには、ソケットごとに1つのスレッドが必要です。または、ブロッキングソケットを使用しないでください。
パンダパジャマ2013年

私のコメントはあなたの答えの最初のバージョンに対するものでしたが、その間、あなたはそれを編集して修正しました、私が言ったことを忘れてください:D
Grimshaw
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.