LoginSignup
16
4

More than 3 years have passed since last update.

RakNetに関して自分なりにまとめてみた

Last updated at Posted at 2019-04-06

RakNetの仕組みを日本語で解説した記事が無かったため勉強ついでにまとめていこうと思います。

RakNetとは

C++で開発されたクロスプラットフォームなゲーム向けネットワークエンジンです。現在は開発が終了しているため基本的にRakNet自体の更新はありません。SLikeNetとして有志の方々が開発を継続していたりします。RakNetはMinecraft統合版やテラリアなどの有名なゲームにも使われています。

特徴

UDPを使用しますが、TCPのようなシーケンス番号や確認応答、コネクション管理、ウィンドウ制御などが実装されているのでUDPの速さをキープしつつ欠点である信頼性を克服しています。使いやすさとパフォーマンスを重視して作られているので手軽にプロジェクトへ導入できます。
※この記事では使い方には触れません。

RakPeer

RakPeerInterface.h
RakPeer.h
RakPeer.cpp

RakNetライブラリのコア的存在です。ほとんどの通信に関する操作はRakPeerを介して行われるでしょう。RakPeerはサーバにもクライアントにもなり得ます。インスタンス化時に最大接続数を指定する必要があるのでRakNetを使用したプロジェクトを考える際は注意です。

RakNetのUDTをベースとしたアーキテクチャなので先にそちらを学んでおくとソースコードも読みやすいと思います。
UDTについて軽くまとめました

Packet

// RakNetTypes.h 一部省略しています。
struct Packet
{
    SystemAddress systemAddress;
    RakNetGUID guid;
    unsigned int length;
    BitSize_t bitSize;
    unsigned char* data;
};

SystemAddress

IPアドレスとポート番号を保持します。RAKNET_SUPPORT_IPV6を指定してコンパイルすることでIPv4とIPv6両方を扱えるようになります。パケット受信時にセットされます。

RakNetGUID

RakNetではピアをIP+PortではなくGUIDで識別します。プロキシのようなネットワークトポロジーの実装を可能にするためです。コネクションが確立されるまでは受信したパケットにはUNASSIGNED_RAKNET_GUIDが設定されます。

Length

dataの長さをbyteで表します。lengthに対しbitSizeではbit単位でdataの長さを表します。通常length == 8 * bitSizeでしょう。

Data

受信したパケットの生データが指定されています。RakPeerは受信したパケットの内容を新しく用意したメモリ領域にコピーするので処理後にメモリの解放が必要になります。解放は簡単です。RakPeerインスタンスのDeallocatePacketにPacketのポインタを渡すだけです。

Priority

PacketPriority.h

パケット送信の際、優先度を設定することができます。

  • IMMEDIATE_PRIORITY
  • HIGH_PRIORITY
  • MEDIUM_PRIORITY
  • LOW_PRIORITY

Priorityには以上の4つがあり、送信キューから2の倍数ずつ送信されます。
ex) IMMEDIATE=>8つ、HIGH=>4つ、MEDIUM=>2つ、LOW=>1つ

Reliability

PacketPriority.h

  • UNRELIABLE
  • UNRELIABLE_SEQUENCED
  • RELIABLE
  • RELIABLE_ORDERED
  • RELIABLE_SEQUENCED
  • UNRELIABLE_WITH_ACK_RECEIPT
  • RELIABLE_WITH_ACK_RECEIPT
  • RELIABLE_ORDERED_WITH_ACK_RECEIPT

UNRELIABLE

UNRELIABLEは単純なUDP通信と同じで信頼性が無く到達確認や再送などもしません。シークエンス番号が重複した際にはパケットを破棄します。

RELIABLE

RELIABLEでは到達確認と再送が行われるので確実にパケットを送信することができます。
必ずパケットは相手へ到達しますが、パケットが前後している可能性があるので注意

SEQUENCED

アプリケーションへ渡すパケットの順番を指定します。
SEQUENCEDではシークエンス番号が新しいものだけを受け付けます。
SequenceNum:1 => SequenceNum:3 => SequenceNum:2
この場合シークエンス番号の2は破棄されます。

ORDERED

アプリケーションへ渡すパケットをシークエンス順にし、必ず連番で渡します。
UNRELIABLEにORDEREDが無いのはこのためです。パケットが必ず届くことが条件です。

*WITH_ACK_RECEIPT

到達が確認されたことをアプリケーションに通知してほしい際に設定します。例として、再送が行われる際にパケットの内容を最新の情報へ書き換えてから送信することができます。

Ordering Streams

ORDEREDなパケットシークエンスの待機バッファ(チャンネル)が32個用意されています。SEQUENCEDにも最新のシークエンス番号を保持するチャンネルが同じく32個用意されています。

Algorithm for blending ordered and sequenced

ORDEREDなチャンネルにSEQUENCEDな機能を追加するアルゴリズムです。
ORDEREDなチャンネルの最新シークエンス番号をインクリメントすると同時にSEQUENCEDなチャンネルの最新シークエンス番号を0にリセットするだけです。
https://github.com/facebookarchive/RakNet/blob/master/Source/ReliabilityLayer.h#L423-L439

MessageID Types

MessageIdentifiers.h

MessageIDはパケットのタイプを表します。パケットのデータの先頭byteがこれにあたります。パデフォルトのパケットのID一覧はDefaultMessageIDTypesに定義されています。ユーザ定義のパケットを実装する際はID_USER_PACKET_ENUM以降の値を使用してください。

参考資料

http://www.jenkinssoftware.com/
http://www.jenkinssoftware.com/raknet/manual/congestioncontrol.html

※追記予定です。。。

16
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
4