# 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 ```c# ServerInterface serverobj = mServer.newServer( string serverName, int port ) ``` Create the client ```c# ClientInterface clientobj = mServer.newClient( string HostNameOrIP, int Port ) ``` Sending data from the server ```c# 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 ```c# 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 ```c# 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 ```c# clientobj.onServerConnected += () => { // When the client establishes a connection with the server }; clientobj.onServerDisconnected += () => { // fires if the connection drops }; ``` Receiving data ```c# // 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. ```c# 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 ```c# 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 connectedUsers = new List(); 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](https://choosealicense.com/licenses/mit/)