はじめに
いつか自分が忘れる気がするのでその時の為のメモ
ネットワークの通信速度について
ボトルネックは色々あるが、ネットワークは基本的に遅い(詳しくは参考記事を読んで)。
内容
http2
http2のコネクション上などを活用するリアルタイム性のあるTCPの場合、3wayハンドシェイクをしといて、コネクションを維持する。ここまではまぁboot処理なので許せる。
で、パケットを送信して、ちゃんと届いたら届いたってパケットをもらって、そうしたらそのパケットの送信が完了する。もし届いてなかったら再度そのパケットを送信する。
UDP
UDPの場合3wayハンドシェイクもしないでいきなりパケットを送信できる。(この部分のメリットは個人的にはhttp2のコネクションが使いやすい現在だとメリットにはならないかなと)
で、ちゃんと届いたよってレスポンスを省いて片道切符にしている。
単純にパケットが往復しなくて良いのでパケットの送信完了までにかかる時間がだいたい倍ぐらい早い(ルーターやパケット受信完了したパケットを作って送り出す処理もあるけどそこは置いとく)。
TCPの場合は道中でパケットロスを3回した場合は、+1回の4回送信するので大まかに4倍 + 待機時間ぐらいがかかる。パケット受信したよってメッセージが届く待機時間もあるので。
パケット到達の信頼性を犠牲にする代わりにこのメリットがあり、そこがデメリットでもある。
ゲーセンのネットワーク越しの格闘ゲーム等で30fps or 60fpsを達成する
参考記事に書いてある内容が正しければ富山から大阪でパケット送信の片道にかかる時間は10ms以上。仮にこれを20msと過程する。
60fpsを達成するには20ms * 60で1200msかかる。1秒を超えてしまう。tcpで往復の場合、パケットロスをしない前提だとタンジュに二倍しても2400msだ。到底60fpsには届かない。また、これに加えて受信したパケットに基づいての計算処理もある。そうすると現実的に30fpsにして、20ms * 30 = 600ms。0.6秒である。これなら非同期処理を上手く組み合わせればいけそう。
また、個体自体は60fpsでシュミレーションしといて、udpで常に個体間の同期を取る実装とかにしてもやっていてラグが少なく気持ちいい気がする。そこはゲームの要件や設計次第。
UDPの使い方
UDPはWebRTCや動画ストリーミング等でも使われる。
で、実際にUDPを使う場合は送られて来る側はパケットを受け止める為のサーバーを起動しておかないといけない。で、特定の端末にパケットを送るためには、いくつかの手順を踏まないといけない。
IPとportの交換
NATというものがあり(現在のNATは大体naptで実装されているらしい)、これはルーター側にインストールされている。これは自分たちの端末とipとポートを結びつける仕事をする。
例えば、端末Aと端末Bが216.58.197.14のアドレスが割り振られているルーターの下にいるとする。そうすると、216.58.197.14にパケットが送られてもどの端末に振ればいいかわからない。なので、端末毎に216.58.197.14 + ポート番号が割り振られる。この仕事をNATがしている。
なので、STUNサーバーを用意し、自身がグローバルからみたらどんなIPで何番のポートが割り振られるのか問い合わせて、UDPで通信対象に対して知らせないといけない。知らせたら通信対象はこの人のこのポートに今後UDPでパケット投げればいいんだね!って伝わる。
これでUDP通信が利用できる。
NATの問題
しかし、NATの実装の中にこんな設定がある。リクエストの度にその端末に割り振るポートを変える設定だ。それがもしされている場合、このままだと以前割り振られていたポートに対して相手はパケットを送り続けてしまう。これはまずい。
これを解決するためにはいくつかの方法があるが、その中でメジャーな手法としてはTURNサーバーを用意することだ。
TURNサーバーのNATは毎回割り振られない設定にする。
TURNサーバーという奴が送信元と送信先をTCPコネクションで繋ぎっぱなしにして、UDPが端末Aから届いたら繋いであるTCPコネクションで端末Bに配信するようにする。
様は、NATの設定がされていなかったら、TURNは出てこない。されていたらTURNサーバーの出番だ。
しかし、TURNサーバーが出てくるってことはかなりマズイ。どうまずいかというと、TCPを使っているのでUDPの片道の利点が消える所だ。結局往復するという。ならはじめからtcpでやればいいじゃないかと。しかも一度TURNをパケットが経由するから追加でかなり遅い。
結論だけいうと以外とこの設定がされていないNATのシェアが多いらしい。(この調査は確かどこかのドキュメントに書いてあったが忘れた
なので、快適に使える人は使えて、TURN使う場合は、残念でした〜って感じです。なのでゲーセンでこの手の個体を置く場合はネットワークの設定やら設計から関わったり調子する必要があるぽい。
結論
面白かった。ゲーセンのネットワーク越しのハイパフォーマンスな格闘ゲームとかなんかその手の奴作ってみたい感ある。
参考記事
https://www.slideshare.net/yhonjo/tcpudp-81497235
https://qiita.com/okyk/items/a405f827e23cb9ef3bde
https://qiita.com/voluntas/items/fd5d633a10272720978d