TCP Server

TCP server is one of the three real-time communication servers of Diarkis where you are able to implement your custom “commands'' for your applications. Commands are formatted packets sent from the client and handled on the server. This is how Diarkis server clusters interact with the client.


The sample code below is generated by the boilerplate from the builder server.

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 Configurations

connectionTTL

10

Connection TTL in seconds. Default is 10 seconds.

address

“127.0.0.1”

Address for TCP server to bind.

nic

“eth0”

Name of a network interface to retrieve binding address from for TCP server.

port

“7200”

Port for TCP server to bind. The TCP server automatically looks for available ports starting from the given port.

noDelay

false

If set to true, it disables Nagle’s algorithm. (No buffering before writing)

enableEncryption

true

If set to false, it disables packet encryption and decryption. HTTP has to set the same configuration.

NOTE: For Cloud environment, address should be the private IP address and environment variable DIARKIS_CLOUD_ENV should be used together.

 

Using Environment Variables In Configurations

Diarkis has auto-replace features with environment variables for configurations.

You add special syntax values in your configurations and those values will be replaced by environment variables.

Environment variable: DIARKIS_TEST=127.0.0.1


Configuration: “address”: “{$DIARKIS_TEST}”

The value of “address” will be “127.0.0.1”.

 

Shutdown Time Of Server

Servers in the Diarkis cluster waits for the connected client to reconnect to another server when it is shutting down. A server becomes “offline” when it receives SIGTERM. When in offline mode, the server starts to prepare for shutdown.

All connected clients receive offline notifications and raise the “OnOffline” event. Servers in offline mode will not accept new clients and will not allow new rooms and groups to be created. The offline servers wait for all connected clients to disconnect from the server, but the server has a timeout and if the timeout expires, it will shutdown without waiting for the clients.

Default timeout is 10 seconds.

How to change the default timeout by environment variable:

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

 

How To Write Custom Command For TCP Server

Commands are formatted packets sent from the client to Diarkis server cluster and handled by the server. This is how Diarkis communicates with its clients. Command implementation interface is uniform across all network protocols.

The sample code below is generated by the boilerplate from the builder server.

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)
}

 

Differences Between ServerRespond and ServerPush

Diarkis client has two types of packet reception events. Response and Push.

Response packets have “status” similar to HTTP responses. This is typically used as a response to a command execution. Push does not have “status” unlike Response. 

Push packets are usually sent from Diarkis server cluster without clients asking for them.

An example of push packets would be broadcast messages from a room.

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)