このフォーラムの人々はおそらくファイアウォールとルーターについて最もよく知っていると思うので、ここでこの質問をします。
マルチプレイヤーゲームを設計していて、データをクライアントに自発的にプッシュしたいとします。おそらく、クライアントが常にサーバーにポーリングして変更を確認するよりも効率的で、サーバーにかかる負荷が少ないからです。
私の理解から、今日のほとんどのコンピューターにはファイアウォールがあり、多くのホームコンピューターもルーターの後ろにあります。そのため、パケットを送信しただけでは、特にルーターがパケットのルーティング先のPCを認識していないため、ブロックされる可能性があります。
ブロックされずにデータをプッシュする良い方法は何ですか?
どのような状況で、ファイアウォールはデフォルト設定のPCでパケットを通過させますか?
そして、ルーターはどのPCにパケットをルーティングするかをどのようにして知るのでしょうか?
この質問が大きすぎないことを願っています。私が尋ねた質問はすべて関連していると思います。そうでない場合は、関連性が低い可能性があるため、ルーターに関する最後の質問を削除します。
編集:私は自発的にパケットを送信すると言いますが、ユーザーがゲームにログインして自分のIPを送信した後でないと意味します。
編集2:(コメントへの回答)
ゲームはインターネット上にあります。
トラフィックの数-最初はおそらく100人の同時ユーザーがいますが、数百人までスケーラブルでなければなりませんが、答えが変わった場合により多くのサーバーを用意するかもしれないので、両方のケースの解決策を聞きたいと思います。
レイテンシ-可能な限り低くする必要があります(リアルタイムゲーム)。
ほとんどのファイアウォールとNATボックスはサーバーが内部からパケットを送信したマシンに返信できるようにするために一般的です。それ以外はすべてEdgeケースまたは異常な動作です。したがって、ゲームクライアントはあなたへの接続を開始できます。そのチャネルで話を戻すことができると想定できます。その場合の目標は、接続を維持することです。TCPとUDP、NATボックスは、何も送信されない場合、最終的にアプリケーションをタイムアウトします。
シンプルでわかりやすい、ほとんどのNATルーターは、UDPパケットがそれらを送信したホストに戻ることを許可します。リアルタイムゲームでは、これは通常のプロトコルであるため、フレームの並べ替えは行われません。ドロップされたパケットに対しては実行されません。ゲームとそのサーバーは、プロトコル内からそれらの状態を同期する必要があります。1分間の無音の後、接続が忘れられることを期待してください。DD-WRTボックスのデフォルトは2分です。
接続の順序を維持するオーバーヘッドは、ゲームからシステムにシフトされます。パケットはアプリケーションに順番に到着しますが、これにより、パケットがドロップしたり、コンピュータに到着したときに、不要な遅延が発生したりすることがあります。少なくともRFCによると、NATボックスは、確立されたTCP接続を少なくとも2時間開いたままにしておく必要があります。現実的には、5分以内にしてください。たとえば、DD-WRTルーターは10で忘れてしまいます。
突然パケットを送信することはありません。クライアントが誰で、どこにあるのかを知る必要があります。したがって、通常のモデルは次のとおりです。各クライアントは、サーバーへのTCP=接続を開きます。接続はそこにあります。サーバーがクライアントに何か言うときは、サーバーにそれを書き込みます。関連する接続。
アイドル接続ではパケットは発生しません。一部のルーター/ファイアウォールは長時間アイドル状態であった接続を強制終了する傾向があるため、実際にはwantでパケットを時々送信する必要があります( " 「長すぎる」は「5分」のように短いこともあります)。
一部のネットワークでは、外部TCP=接続が拒否され、すべてのネットワークアクティビティがHTTPプロトコルの下でプロキシを経由する必要があります(一部のビジネスネットワークでは、特別なゲームをプレイするためのファイアウォールルールは多少不快になる可能性があります。通常の回避策はHTTPS(つまりSSL)を実行することです。これは、プロキシが一般的な双方向TCPフォワーダー( CONNECT
プロキシコマンド)。これもブロックされている場合は、ダミーのHTTPリクエストを送信したり、サーバーに「無制限」の応答(明示的な「 Content-Length 'header)by small chunks。ディスカッションについては このブログ投稿 を参照してください。
迅速な対応:
ホームルーターまたはファイアウォールの一般的な問題は、外部接続を許可し、内部接続を許可しないことです。
各ブランド/モデルは、バイパスまたは内部ポートマッピングを可能にする一般的に同じ機能を備えています。ただし、正確な方法(GUI、設定)はまったく異なる(したがって複雑な)場合があります。
clientsを(サーバーに)接続する方が確実に安全です。ただし、主に(serverから)を送信するには、まずclientで外部接続を確立し、次にそのパスでパケットをリッスンします。
簡単に言えば、クライアントはクライアントとして動作する必要があります。つまり、「プッシュされた」データの接続を開始します。
あなたが言うように、UDPおよびTCP接続はほとんどのファイアウォールを通過せず、ほとんどのNATルーターを通過しません。
実際、ユーザーエンドで開始されたソケットを使用しても、ポート80を使用することで最良のカバレッジを取得できます。少なくとも comet を検討する必要があります
(ただし、IMEの場合、ほとんどのMORPGは、ユーザーが着信接続を明示的に許可することに依存しています。)
これは問題の1つです websockets は解決することを目的としています。
どちらのアーキテクチャでも、接続ごとに1つのスレッド/プロセスを持つ従来のサーバーモデルを使用すると、深刻なスケーラビリティの問題が発生します。 (node.jsを読んでください)。
当然のことながら、node.jsは非常に優れたWebSocketサポートを備えています。