TCPサーバー

TCPサーバーは、Diarkisの3つのリアルタイム通信サーバーのうちの1つで、アプリケーションのためのカスタム「コマンド」を実装することができます。コマンドとは、クライアントから送信され、サーバーで処理されるフォーマットされたパケットのことです。これは、Diarkisのサーバークラスターがクライアントと対話する方法です。


以下のサンプルコードは、ビルダーサーバーからボイラープレートによって生成されたものです。

servers/tcp/main.go

package main

import (
    "fmt"
    "github.com/Diarkis/diarkis"
    "your/project/cmds"
    "github.com/Diarkis/diarkis/log"
    "github.com/Diarkis/diarkis/mesh"
    "github.com/Diarkis/diarkis/server"
    "os"
)

func main() {
    rootpath, err := os.Getwd()
    if err != nil {
        panic(err)
    }
    log.Setup(fmt.Sprintf("%s/configs/shared/log.json", rootpath))
    // Sets up the internal communication network
    mesh.Setup(fmt.Sprintf("%s/configs/shared/mesh.json", rootpath))
    // Sets up the server as TCP server
    server.SetupAsTCPServer(fmt.Sprintf("%s/configs/tcp/main.json", rootpath))
    cmds.Setup(rootpath)
    // Exposes all commands including built-in commands and custom commands
    cmds.ExposeServer()
    diarkis.Start()
}

 

TCP サーバの設定

connectionTTL

10

接続のTTL(秒)。デフォルトは10秒です

address

“127.0.0.1”

バインドするTCPサーバーのアドレス

nic

“eth0”

TCPサーバーのバインドされたアドレスを取得するネットワークインターフェースの名前

port

“7200”

TCPサーバがバインドするポートです。TCPサーバーは、指定されたポートを起点に、利用可能なポートを自動的に探します

noDelay

false

trueに設定すると、Nagleアルゴリズムを無効にします(書き込み前のバッファリングなし)

enableEncryption

true

falseに設定すると、パケットの暗号化と復号化が無効になります。HTTPも同様の設定をする必要があります

※ クラウド環境では、addressはプライベートIPアドレスとし、環境変数DIARKIS_CLOUD_ENVを併用してください。

環境変数の設定

Diarkisには、コンフィグレーションの環境変数による自動置換機能があります。
設定の中にあらかじめ定められた値を追加すると、その値は環境変数で置き換えられます。

環境変数: DIARKIS_TEST=127.0.0.1


設定ファイル: “address”: “{$DIARKIS_TEST}”

「アドレス」の値は「127.0.0.1」になります。

 

サーバーのシャットダウン時の処理

Diarkisクラスターのサーバーは、シャットダウン時に、接続されたクライアントが他のサーバーに再接続するのを待ちます。サーバーは、SIGTERMを受信すると「オフライン」になります。オフラインモードになると、サーバーはシャットダウンの準備を開始します。

接続されているすべてのクライアントは、オフライン通知を受け取り、「OnOffline」イベントを発生させます。オフラインモードのサーバーは、新しいクライアントを受け入れず、新しいルームやグループの作成を許可しません。オフラインのサーバーは、接続されているすべてのクライアントがサーバーから切断されるのを待ちますが、サーバーにはタイムアウトがあり、タイムアウトが切れると、クライアントを待たずにシャットダウンします。

デフォルトのタイムアウトは10秒です。

環境変数でデフォルトのタイムアウトを変更する方法:

# This will change the server shutdown timeout to 60 seconds
DIARKIS_SHUTDOWN_TIMEOUT=60

 

TCPサーバのカスタムコマンドの書き方

コマンドとは、クライアントからDiarkisサーバークラスタに送信され、サーバーによって処理されるフォーマットされたパケットのことです。これにより、Diarkisはクライアントと通信します。コマンドの実装インターフェースは、すべてのネットワークプロトコルで統一されています。
以下のサンプルコードは、ビルダーサーバからのボイラープレートによって生成されたものです。

cmds/custom/main.go

package customcmds

import (
    "github.com/Diarkis/diarkis/log"
    "github.com/Diarkis/diarkis/server"
    "github.com/Diarkis/diarkis/user"
)

const customVer = 2 // 0 and 1 are reserved the Diarkis internal
const helloCmdID = 10
const pushCmdID = 11

var logger = log.New("CUSTOM")
// this is called in cmds/main.go
func Expose() {
    server.HandleCommand(customVer, helloCmdID, helloCmd)
    server.HandleCommand(customVer, helloCmdID, afterHelloCmd)
    server.HandleCommand(customVer, pushCmdID, pushCmd)
}

func helloCmd(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)) {
    // payload is the byte array sent from the client
    logger.Debug("Payload %#v SID:%s - UID:%s", payload, userData.SID, userData.ID)
    // if this is executed as UDP, reliable = true means sending the packet as an RUDP packet
    reliable := true
    // we send a response back to the client with the byte array sent from the client
    userData.ServerRespond(payload, ver, cmd, server.Ok, reliable)
    // move on to the next command handler if there is any
    next(nil)
}

func afterHelloCmd(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)) {
    logger.Debug("This is executed after Hello command has been handled")
    next(nil)
}

func pushCmd(ver uint8, cmd uint16, payload []byte, userData *user.User, next func(error)) {

    // payload is the byte array sent from the client
    logger.Debug("Payload %#v SID:%s - UID:%s", payload, userData.SID, userData.ID)
    // if this is executed as UDP, reliable = true means sending the packet as an RUDP packet
    reliable := true
    // we send a push packet to the client that sent the data to this command
    userData.ServerPush(ver, cmd, payload, reliable)
    // move on to the next command handler if there is any
    next(nil)
}

 

ServerRespondとServerPushの違い

Diarkisクライアントには、2種類のパケット受信イベントがあります。レスポンスとプッシュです。

レスポンスパケットは、HTTPレスポンスに似た「ステータス」を持っています。これは通常、コマンド実行の応答として使用されます。PushはResponseと異なり、「ステータス」を持ちません。 

プッシュパケットは通常、クライアントが要求しなくてもDiarkisサーバークラスターから送信されます。

プッシュパケットの例としては、部屋からのブロードキャストメッセージなどがあります。

Response

// payloadByteArray is the message byte array to be sent to the client
// cmdVer is the version of the response 0 and 1 is reserved by Diarkis internal.
// cmdID is the command ID of the response.
// response status: OK = 1, BAD = 4, and ERROR = 5
// reliable is used for UDP server only and if this is set to true, the response becomes RUDP
userData.ServerRespond(payloadByteArray, cmdVer, cmdID, status, reliable)

Push

// payloadByteArray is the message byte array to be sent to the client
// cmdVer is the version of the response 0 and 1 is reserved by Diarkis internal.
// cmdID is the command ID of the response.
// reliable is used for UDP server only and if this is set to true, the response becomes RUDP
userData.ServerRespond(cmdVer, cmdID, payloadByteArray, reliable)