29

NodeJS を使用してマルチプレイヤー ゲームを作成しようとしていますが、クライアント間でアクションを同期させたいと考えています。

クライアントとサーバー間のレイテンシー (リクエストがクライアントに戻ってくるまでの時間) を見つける最良の方法は何でしょうか?

私の最初のアイデアは、クライアント #1 がリクエストでタイムスタンプを送信できるので、クライアント #2 がクライアント #1 のアクションを受け取るときに、リクエストの遅延を取り除くためにアクション速度を調整するというものでした。しかし、問題は、2 つのクライアントのシステム日付時刻が同一でない可能性があるため、クライアント #1 の要求のリール遅延を 2 人が知ることができないことです。

もう 1 つの解決策は、サーバーのタイムスタンプを使用することでしたが、クライアントのレイテンシを知るにはどうすればよいでしょうか?

4

6 に答える 6

27

レイテンシが重要なゲームを実装しているため (そしてそのようにタグ付けしたため)、WebSockets またはSocket.IOを使用していると仮定します。

サーバーはおそらく、クライアントごとにこれを測定して追跡する必要があると思います。

おそらく、サーバーがクライアントに要求できるある種の ping アクションを実装したいと思うでしょう。クライアントがリクエストを受け取るとすぐに、サーバーにレスポンスを返します。次に、サーバーは 2 で割り、そのクライアントのレイテンシーを更新します。おそらく、サーバーが各クライアントで定期的にこれを行い、最後のいくつかを平均して、突然の一時的なスパイクによって奇妙な動作が発生しないようにする必要があります。

次に、あるクライアントから別のクライアントに送信 (またはブロードキャスト) する必要があるメッセージがある場合、サーバーは client1 のレイテンシーを client2 のレイテンシーに追加し、これをレイテンシー オフセットとしてメッセージの一部として client2 に伝達できます。client2 は、client1 でのイベントがそのミリ秒前に発生したことを認識します。

サーバーでこれを行うもう 1 つの理由は、一部のブラウザー Javascript タイムスタンプが不正確であることです: http://ejohn.org/blog/accuracy-of-javascript-time/。node.js のタイムスタンプは、V8 (数少ない正確​​なタイムスタンプの 1 つ) と同じくらい (またはそれ以上) 正確であると思います。

于 2010-11-01T19:07:14.130 に答える
6

リクエストでタイムスタンプを送信するために私が通常行うこと:

  1. クライアントで を作成し、JSON リクエストごとにサーバーにnew Date()送信します。timestamp: date.getTime()
  2. サーバーでは、リクエストを受信したら、processed: (new Date()).getTime()オブジェクトに a を入れます。
  3. リクエストを処理します。
  4. 応答にtimestamp、要求からの と新しい処理済みフィールドprocessed: (new Date()).getTime() - req.processedを入力します。これには、要求の処理にかかったミリ秒数が含まれるようになりました。
  5. クライアントでは、応答を受信するときにtimestamp(pt 1 で送信されたものと同じ) を取得し、現在の時刻からそれを減算し、処理時間 ( processed) を減算すると、「実際の」ping 時間 (ミリ秒) が得られます。

一方向の通信であっても、ping 時間には常に要求と応答の両方の時間を含める必要があると思います。これは、「ping 時間」と「レイテンシー」の背後にある標準的な意味であるためです。一方向の通信で、遅延が実際の ping 時間の半分に過ぎない場合、それは単なる「良いこと」です。

于 2010-11-03T11:58:39.373 に答える
1

これは、ping をテストするための非常に簡単で汚いスクリプトです。ブラウザでhttp://yourserver:8080にアクセスし、コンソール (ssh ターミナル) を確認してください。

var http = require('http');
var io = require('socket.io');

server = http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.write('<html>\n');
  res.write('  <head>\n');
  res.write('    <title>Node Ping</title>\n');
  res.write('    <script src="/socket.io/socket.io.js"></script>\n');
  res.write('    <script>\n');
  res.write('        var socket = new io.Socket();\n');
  res.write('        socket.on("connect",function(){ });\n');
  res.write('        socket.on("message",function(){ socket.send(1); });\n');
  res.write('        socket.connect();\n');
  res.write('    </script>\n');
  res.write('  </head>\n');
  res.write('  <body>\n');
  res.write('    <h1>Node Ping</h1>\n');
  res.write('  </body>\n');
  res.write('</html>\n');
  res.end();
});
server.listen(8080);

console.log('Server running at http://127.0.0.1:8080/');

var socket = io.listen(server);

socket.on('connection',function(client){
  var start = new Date().getTime();
  client.send(1);
  client.on('message',function(message){ client.send(1);  console.log( new Date$
  client.on('disconnect',function(){});
});

カリフォルニアとニュージャージーの両方で専用リソースを備えた大きなvpsボックスでpingがかなり高い(往復200〜400ミリ秒)ように見えるので、これについて非常に興味があります。(私は東海岸にいます) vps ボックスが非常に多くのトラフィックを処理しているため、vps ボックスに多くの遅延があるに違いありません。

私が得たのは、同じクライアントから同じサーバーへのLinuxターミナルからの通常のpingは、平均で11ミリ秒で、10倍も低いということです...私は何か間違ったことをしているのか、node.js/socketで何か遅いのですか. io/ウェブソケット?

于 2010-11-03T12:41:54.323 に答える
0
于 2014-03-14T13:05:18.463 に答える