2026-07-01 12:15:52 -07:00
2026-07-01 10:49:47 -07:00
2026-07-01 10:49:47 -07:00
2026-07-03 17:46:22 -07:00
2026-08-03 13:25:28 -07:00

Server Standard

This is a central server and client model based server. The basis of the networking is on msgpack. works on IPv4 only at the moment. In a future release I might add IPV6 but not on any roadmap. Fully threaded and asynchrous to scale easily.

Library

This is a library with a CLI attached to it to show usage. You can send and receive any data type except the standard 'Object' type

Usage

Follow the example listed in Program.cs inside the CLI Note: All datatypes that are sent to the server, The server needs to be aware of when in Athouritative mode.

Create the server

ServerInterface serverobj = mServer.newServer( string serverName, int port )

Create the client

ClientInterface clientobj = mServer.newClient( string HostNameOrIP, int Port )

Sending data from the server

serverobj.SendClient( string UserName, dynamic Object )   // Sent as a TCP packet to the client
serverobj.SendAllClients( dynamic Object )                // Sent as a TCP packet to all clients

Sending data from the client

clientobj.SendServer( dynamic Object )                    // Sent as a TCP packet to the server
clientobj.SendClient( string UserName, dynamic Object )   // Sent as a UDP packet directly to the client
clientobj.SendAllClients( dynamic Object )                // Sent as a UDP packet directly to all clients

Wiring up the event handlers

Users Connecting and Disconnecting


serverobj.onUserConnected += (TcpClientConnection connection) => {
    // When a new user joins the server this fires
};

serverobj.onUserDisconnected += (TcpClientConnection connection) => {
    // When a user leaves the server this fires
};

clientobj.onUserConnected += (UDPEndpoint remoteUser) => {
    // When a new user joins the server this fires
};

clientobj.onUserDisconnected += (UDPEndpoint remoteUser) => {
    // When a user leaves the server this fires
};

The client also gets the ability to see if the server disconnected


clientobj.onServerConnected += () => {
    // When the client establishes a connection with the server
};

clientobj.onServerDisconnected += () => {
    // fires if the connection drops
};

Receiving data


// When a packet is received from either the Server or another user this fires
// 'data' here can be any function tagged mPacket
// use this format as an example
serverobj.onDataReceived += (dynamic data) => {
    switch (data as object)  {
        case UserConnectionPacket packet:
            userConnected(packet); 
            break;

        case UserDisconnectedPacket packet:
            userDisconnected(packet);
            break;

        case null:
            Console.WriteLine("Received a null packet.");
            break;

        default:
            Console.WriteLine($"Packet of type {data.GetType().Name} not accounted for");
            break;
    }
};

In order to send a packet you need to define the packet as an mPacket
an mPacket requires a unique ID, This ID allows the packet to be decyphered on the receving side
Therefore every mPacket requires a unique ID. The ID field is 8 bytes so the biggest number is 0xFF.

By default the mPacket will work on both the server connection and the client connections. But due
to the limited function space you can reuse ID's if you map them out correcty because there are 2
packet scopes as shown below.

public enum PacketUsage {
    ClientToClient = 0x01,    // Used only for Client To Client Connections
    ClientToServer = 0x10,    // Used only for Server To Client and Client To Server connections
}
// ClientToServer packets are also used for ServerToClient connections as well

// If you would like to send a packet to both the clients and to the server you need to either use
// the base function or add the bitwise or. Some examples are listed below

[mPacket(0x01, PacketUsage.ClientToClient)] // Exclusivly for client to client usage
[mPacket(0x01, PacketUsage.ClientToServer)] // Exclusivly for client to server usage
// These 2 packets can exist at the same time becuase the scope is different even though the packet id is already used

[mPacket(0x02)] // This can be used for both connection types therefor the ID needs to be unique
[mPacket(0x03, PacketUsage.ClientToClient | PacketUsage.ClientToServer)] // Same as the line just before

Full example to tie it all together

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Mistox;
using Mistox.Attributes;
using Mistox.Server;

[mPacket(0x01)]
class HelloPacket {
  public string Name { get; set; } = "";
}

[mPacket(0x02, PacketUsage.ClientToServer)]
class GoodbyePacket {
  public string Name { get; set; } = "";
}

class Main {

  ServerInterface serverobj;
  List<TcpClientConnection> connectedUsers = new List<TcpClientConnection>();

  public async Task Main(){
    serverobj = mServer.newServer( "serverName", 1234 );
    serverobj.onDataReceived += ReceiveThread;
    serverobj.onUserConnected += (TcpClientConnection user) => {
      connectedUsers.Add(user);
    };
    serverobj.onUserDisconnected += (TcpClientConnection user) => {
      connectedUsers.Add(user);
    };

    await serverobj.SendAllClients(new HelloPacket {
      Name = "Jeffey"
    });
  }

  void ReceiveThread(dynamic data){
    switch (data as object)  {
      case HelloPacket packet:
          HelloWasCalled(packet); 
          break;

      case GoodbyePacket packet:
          GoodbyeWasCalled(packet);
          break;

      default:
          Console.WriteLine($"Packet of type {data.GetType().Name} not accounted for");
          break;
    }
  }

  void HelloWasCalled(HelloPacket packet) {
    connectedUsers[0].UserName = packet.Name;
  }

  void GoodbyeWasCalled(GoodbyePacket packet) {
    foreach(var cur in connectedUsers) {
      if (cur.UserName == packet.Name) {
        connectedUsers.Remove(cur);
      }
    }
  }

}

Contributing

All Credits to Derek Holloway

License

MIT

S
Description
No description provided
Readme
6.5 MiB
0 Stars 1 Watchers 0 Forks
v1.0.0
Latest
2026-08-06 10:08:38 -07:00
Languages
C# 100%