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

Results 1 to 1 of 1
  1. #1
    Member Nothilvien is offline
    MemberRank
    Nov 2007 Join Date
    41Posts

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

    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:
    using System;
    using System.Net;
    using Arrowgene.Services.Buffers;
    using Arrowgene.Services.Logging;
    using Arrowgene.Services.Networking.Tcp.Consumer.EventConsumption;
    using Arrowgene.Services.Networking.Tcp.Server.AsyncEvent;
    
    
    namespace Demo
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                new Program();
            }
    
    
            public 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 = new EventConsumer();
                serverConsumer.ClientConnected += ServerConsumerOnClientConnected;
                serverConsumer.ClientDisconnected += ServerConsumerOnClientDisconnected;
                serverConsumer.ReceivedPacket += ServerConsumerOnReceivedPacket;
    
    
                AsyncEventServer server = new AsyncEventServer(IPAddress.Any, 2000, serverConsumer);
                server.Start();
    
    
                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
    
    
                server.Stop();
            }
    
    
            private void LogProviderOnGlobalLogWrite(object sender, LogWriteEventArgs logWriteEventArgs)
            {
                // Writes all logs to console:
               Console.WriteLine(logWriteEventArgs.Log);
            }
    
    
            private void ServerConsumerOnReceivedPacket(object 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 = new 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 = new StreamBuffer();
    
    
                // Write data to it:
                response.WriteInt32(1234);
    
    
                // Send it to the socket:
                e.Socket.Send(response.GetAllBytes());
    
    
    
    
                Console.WriteLine(string.Format("Server: received packet Size: {0}", e.Data.Length));
            }
    
    
    
    
            private void ServerConsumerOnClientConnected(object 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");
            }
    
    
    
    
            private void ServerConsumerOnClientDisconnected(object 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: https://github.com/Arrowgene/Arrowgene.Services

    Or use nuget to import it into your project:
    NuGet: https://www.nuget.org/packages/Arrowgene.Services/


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




Advertisement