Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

[C#][Socket][Library] Help for Server Prototyping / Development

Joined
Nov 20, 2007
Messages
31
Reaction score
9
Hello, I would like to introduce a library which can be used to quickly prototype or power a server.

Often I find myself in the situation that I want to listen on a socket, handle some byte array data and send a response. Usually I will start out with some hacked code just to get it running and at a later point when the prototype proves to be successful I spend a lot of time optimising the socket code.

In order to not always repeat this, I wrote a library that offers the most common task and which one can build a server upon.

The main goals for me were

- No dependencies on other frameworks
- Easy setup / few lines of code
- Configurable
- Usable as a base to build on / not stand in your way
- Fast
- Reading/Writing Data Types from byte arrays

Based on these goals I made the design decisions which might not be in favour of everyone (like it provides a custom logger, even there are far better with proven track record out there). This is mainly build for myself, but maybe it can be of help for you. I'd also be happy about feedback to improve, even with the goals in mind I'm not perfect and might have done something horrible wrong :), so keep that in mind and audit the code for yourself if that is something you want to use.


The code includes a 'Playground' project, showing some examples. I also got to write a few (very little) unit tests. It probably lacks some solid documentation on usage examples.

For most servers where you want to handle all the data yourself the example would look like this:

Code:
[B]using [/B]System;
[B]using [/B]System.Net;
[B]using [/B]Arrowgene.Services.Buffers;
[B]using [/B]Arrowgene.Services.Logging;
[B]using [/B]Arrowgene.Services.Networking.Tcp.Consumer.EventConsumption;
[B]using [/B]Arrowgene.Services.Networking.Tcp.Server.AsyncEvent;


[B]namespace [/B]Demo
{
    [B]public class [/B]Program
    {
        [B]public static void [/B]Main([B]string[/B][] args)
        {
            [B]new [/B]Program();
        }


        [B]public [/B]Program()
        {
            // Listen for all logs from the library:
            LogProvider.GlobalLogWrite += LogProviderOnGlobalLogWrite;
            
            
            // Create a consumer (There are a few provided by the library, 
            // or you can create your own consumer by implementing the 'IConsumer' interface and 
            // passing that instance to the 'AsyncEventServer' constructor. 
            // The consumers methods will be called on important occasion (New Client, Client DC, Data Arrived)


            EventConsumer serverConsumer = [B]new [/B]EventConsumer();
            serverConsumer.ClientConnected += ServerConsumerOnClientConnected;
            serverConsumer.ClientDisconnected += ServerConsumerOnClientDisconnected;
            serverConsumer.ReceivedPacket += ServerConsumerOnReceivedPacket;


            AsyncEventServer server = [B]new [/B]AsyncEventServer(IPAddress.Any, 2000, serverConsumer);
            server.Start();


            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();


            server.Stop();
        }


        [B]private void [/B]LogProviderOnGlobalLogWrite([B]object [/B]sender, LogWriteEventArgs logWriteEventArgs)
        {
            // Writes all logs to console:
           Console.WriteLine(logWriteEventArgs.Log);
        }


        [B]private void [/B]ServerConsumerOnReceivedPacket([B]object [/B]sender, ReceivedPacketEventArgs e)
        {
            // Creat an buffer to read the data.
            // StreamBuffer is provided by the library and backed by a Stream.
            // It exposes methods to read write the data, by passing an byte[] in the constructor,
            // we are able to read the data.
            IBuffer received = [B]new [/B]StreamBuffer(e.Data);
            // If we want to acces the buffer from the beginning, the position needs to be set to the start:
            received.SetPositionStart();


            // Now we can call read methods to read data types sequentially from the underlying byte array.
            // received.ReadInt32();


            // Create a response with the StreamBuffer helper:
            IBuffer response = [B]new [/B]StreamBuffer();


            // Write data to it:
            response.WriteInt32(1234);


            // Send it to the socket:
            e.Socket.Send(response.GetAllBytes());




            Console.WriteLine([B]string[/B].Format("Server: received packet Size: {0}", e.Data.Length));
        }




        [B]private void [/B]ServerConsumerOnClientConnected([B]object [/B]sender, ConnectedEventArgs e)
        {
            // A new client established a connection with the server.
            // You can find the instance in the evenet arguments.
            // This is a good point to add the client to a list, incase you want to keep the reference.
            Console.WriteLine("Server: New Client Connected");
        }




        [B]private void [/B]ServerConsumerOnClientDisconnected([B]object [/B]sender, DisconnectedEventArgs e)
        {
            // A client disconnected, the arguments give you the instance of the client.
            // Clean up all referneces you hold to this client, as its not usable anymore.
            Console.WriteLine("Server: Client Disconnected");
        }
    }
}

It starts a server with an EventHandlerConsumer that is provided by the library which will fire events whenever something important happened in the server. It also showcases how to use the StreamBuffer to work with byte arrays.

As mentioned above the library uses a custom logger, to be able to listen to the logs you need to register a method.

The library also has some more advanced features like the ability to send .NET objects over the wire. They will be serialised/deserialised by the library, and it is possible to register handler classes, that notify you with the .NET object whenever you receive it. But this is more useful if you develop your own client or do server to server communication, as for server emulation this will be useless.



If there are any questions or assistance needed please feel free to ask.

You can find the source on github here:
Github:

Or use nuget to import it into your project:
NuGet:


For the future I will probably try to add better documentation and unit tests.
 
Back
Top