# Diarkis RUDP

## 概要

Reliable User Datagram Protocol (RUDP) はデータの到達が保証されるように実装された UDP 通信です。Diarkis クライアントはサーバーとの通信や P2P 通信において RUDP を用いてデータを送信することができ、ゲームの進行に必要不可欠な情報など重要なデータを確実に相手に届けることができます。このページでは Diarkis の RUDP の仕様と設定について説明します。

## Diarkis RUDP の仕様

Diarkis RUDP が確立される組み合わせはサーバー - クライアント間とクライアント - クライアント間 (P2P 通信) があり得ます。一部の機能は P2P 通信でのみ使用が可能です。

Diarkis RUDP ではデータを受信した場合に Acknowledgement (ACK) を返すことでデータが到達したことを相手に知らせます。もし指定した時間以内に ACK の受信が確認できなければ Diarkis クライアントは同じデータを再送します。本ページではこの時間を **RetryInterval** と呼びます。また、同じデータを指定した回数だけ再送してもなお ACK の受信が確認できなければ、タイムアウトによって Diarkis クライアントは相手との通信を切断します。本ページではこの回数を **RetryMaxCount** と呼びます。

P2P 通信における RUDP に限りデータの到達保証に加えてデータの**順番保証の切り替え機能**を提供しています。順番保証機能を有効にすると、アプリケーションが受信するデータの順番が相手ユーザーが送信した順番と一致することが保証されます。Diarkis ライブラリはシーケンシャル番号通りにパケットが受信できるまでアプリケーションにデータを渡しません。順番保証機能を無効にした場合、Diarkis ライブラリはパケットを受信した順番にアプリケーションにデータを渡し、その順番はネットワークの状況や再送パケットの有無によって変わります。

サーバー - クライアント間の RUDP 通信では常に順番保証が有効になります。

## Diarkis RUDP の設定

### RetryInterval の設定

以下の関数を使用することで RetryInterval を調整することができます。

{% code title="udp.h" %}

```cpp
void SetSendRetryInterval(uint32_t minMs, uint32_t maxMs)
```

{% endcode %}

RetryInterval は `minMs` で指定した時間 (ミリ秒) から始まり、クライアントが再送するたびに値が **2 倍**になり、`maxMs` で指定した時間まで上昇します。 例えば minMs=300ms、maxMs=1000ms、RetryMaxCount が 5 回の場合、RetryInterval は 300ms, 600ms, 900ms, 1000ms, 1000ms と変化します。5 回目の再送がタイムアウトした場合クライアントは通信を切断します。

RetryInterval を Exponential に変化させることでクライアントのネットワーク処理負荷を抑えることができます。もし RetryInterval を固定値にしたい場合は `minMS` と `maxMS` に同じ値を指定することでRetryInterval を再送回数にかかわらず常に一定にすることができます。

### RetryMaxCount の設定

以下の関数を使用することで RetryMaxCount を調整することができます。

{% code title="udp.h" %}

```cpp
void SetSendRetryMaxCount(uint32_t count)
```

{% endcode %}

RetryMaxCount は `count` で指定した値になります。

### 順番保証の設定

a. [Diarkis Module](https://help.diarkis.io/diarkis-client/diarkis-module) を利用する場合は `DiarkisP2PBase.h` に定義されている `SendBroadcast` などの関数が持つ `reliability` 引数によって RUDP の動作を制御することができます。`reliability` 引数に列挙型`Reliability` の値を指定してください。

{% code title="DiarkisP2PBase.h" %}

```cpp
System::Result SendBroadcast(const uint8_t* payload, const size_t payloadSize, const Diarkis::Reliability reliability)
```

{% endcode %}

{% code title="common.h" %}

```cpp
enum class Reliability: uint8_t
{
    UNRELIABLE_UNORDERED = 0, // 到達保証なし、順番保証なし (UDP)
    RELIABLE_UNORDERED = 1,   // 到達保証あり、順番保証なし
    RELIABLE_ORDERED = 2      // 到達保証あり、順番保証あり
};
```

{% endcode %}

b. ライブラリを直接使用する場合は以下にある P2P 通信のデータ送信関数において `bFixedOrder` フラグを `true` にして実行します。

{% code title="p2p.h" %}

```cpp
Diarkis::System::Result RSend(const uint8_t* message, size_t messageSize, bool bFixedOrder)
```

{% endcode %}

## 設定における注意事項

* `SetSendRetryInterval` と `SetSendRetryMaxCount` はサーバーとの RUDP 通信に対して設定を行います。P2P 通信における設定は `SetSendRetryIntervalP2P` と `SetSendRetryMaxCountP2P` を使用してください。
* RetryInterval が非常に小さい場合や RetryMaxCount が大きい場合はクライアントは大量のパケットを送信しなければならず、ネットワークの処理負荷が大きくなるのでご注意ください。
