示例#1
0
        /// <summary>
        /// Handles the main functionality and logica of the application
        /// </summary>
        private void Handler()
        {
            bool   recvRequest = true;
            string EOL         = "\r\n";

            string        requestPayload  = "";
            string        requestTempLine = "";
            List <string> requestLines    = new List <string>();

            byte[] requestBuffer  = new byte[1];
            byte[] responseBuffer = new byte[1];

            requestLines.Clear();

            // Try to get the request headers from the client
            try
            {
                //State 0: Handle Request from Client
                while (recvRequest)
                {
                    this._clientSocket.Receive(requestBuffer);
                    string fromByte = ASCIIEncoding.ASCII.GetString(requestBuffer);
                    requestPayload  += fromByte;
                    requestTempLine += fromByte;

                    // Format the string headers to a list of headers
                    if (requestTempLine.EndsWith(EOL))
                    {
                        requestLines.Add(requestTempLine.Trim());
                        requestTempLine = "";
                    }

                    // If the request ends with double end of line it has received the headers
                    if (requestPayload.EndsWith(EOL + EOL))
                    {
                        recvRequest = false;
                    }
                }

                string cookie  = null;
                string session = null;
                string url     = null;
                requestPayload = "";
                // Loop through all the HTTP Headers
                foreach (string line in requestLines)
                {
                    // Remove Accept-Encoding to display the plain HTML
                    bool addLines = !line.Contains("Accept-Encoding");

                    // If the line contains a cookie we will check what algorithm is active and react based on that
                    if (line.Contains("Cookie"))
                    {
                        switch (Algoritme.Get())
                        {
                        case "Cookie Based":
                            cookie = line.Split('=')[1];
                            break;

                        case "Session Based":
                            session = line.Split('=')[1];
                            break;
                        }
                    }

                    // Add the HTTP Header to the requestPayload
                    if (addLines)
                    {
                        requestPayload += line;
                        requestPayload += EOL;
                    }
                }

                // Determine what server we need to connect to
                var selectedServer = _server.GetConnectionInfo(cookie, session);

                // Try to connect to the chosen server
                try
                {
                    TcpClient client = new TcpClient(selectedServer[0], Int32.Parse(selectedServer[1]));
                    var       stream = client.GetStream();

                    // Write the request to the server
                    stream.Write(ASCIIEncoding.ASCII.GetBytes(requestPayload), 0, ASCIIEncoding.ASCII.GetBytes(requestPayload).Length);

                    // If the algorithm is cookie based we need to add a cookie to the response headers
                    if (Algoritme.Get() == "Cookie Based")
                    {
                        string response = null;
                        var    contentLengthIsAvailable = false;
                        var    headersInThePocket       = false;
                        int    contentLength            = 0;


                        StringBuilder responseBytes = null;
                        var           i             = 0;
                        while (true)
                        {
                            // Read all the bytes from the server
                            stream.Read(responseBuffer, 0, responseBuffer.Length);

                            // Convert these bytes to a string and add these to the response string
                            response += Encoding.ASCII.GetString(responseBuffer);

                            // Check if all the headers are received
                            if (response.EndsWith(EOL + EOL))
                            {
                                // Add a "Set-Cookie" header to the response headers
                                response = response.Split(new[] { EOL + EOL }, StringSplitOptions.None)[0];
                                var connectionCookie = selectedServer[0] + ":" + selectedServer[1];
                                response += EOL + "Set-Cookie: fixed-server=" + Algoritme.CalculateMD5Hash(connectionCookie) + EOL + EOL;

                                var headers = response.Split(':');

                                // Determine the Content-Length for further reading
                                var contentLengthAvailable = false;
                                foreach (var header in headers)
                                {
                                    if (contentLengthAvailable)
                                    {
                                        contentLength          = int.Parse(header.Split('\r')[0]);
                                        contentLengthAvailable = false;
                                    }

                                    if (header.EndsWith("Content-Length"))
                                    {
                                        contentLengthAvailable = true;
                                    }
                                }
                                responseBytes      = new StringBuilder(response);
                                headersInThePocket = true;
                            }

                            // Read the body when the headers are in the pocket
                            if (headersInThePocket)
                            {
                                if (contentLength == 0)
                                {
                                    // If the response has nog content-length header we will set it on a default
                                    contentLength = 2000;
                                }
                                if (i < contentLength)
                                {
                                    // As long as the body has not been received we will append the body to our responseBytes
                                    responseBytes.Append(Encoding.ASCII.GetString(responseBuffer));
                                    i++;
                                }
                                else
                                {
                                    var    charResponse = responseBytes.ToString().ToCharArray(0, responseBytes.Length);
                                    byte[] test         = Encoding.ASCII.GetBytes(charResponse);

                                    // Sent the response to the clientSocket
                                    _clientSocket.Send(test);
                                    // Break out of the while loop as we do not need to receive anymore bytes
                                    break;
                                }
                            }
                        }
                    }
                    // If Algorithm "Cookie-Based" has not been selected. We will send everything straight through
                    else
                    {
                        while (stream.Read(responseBuffer, 0, responseBuffer.Length) != 0)
                        {
                            this._clientSocket.Send(responseBuffer);
                        }
                    }

                    // Remove the server from the request for the load Algorithm
                    foreach (var serverRequest in Algoritme.requestPerServer)
                    {
                        if (serverRequest[0] == selectedServer[0])
                        {
                            Algoritme.requestPerServer.Remove(serverRequest);
                        }
                    }

                    client.Close();
                    stream.Dispose();
                }
                // When the recommended server cannot be contacted
                catch (SocketException e)
                {
                    Console.Write("Server has fallen", e);
                    Handler();
                }

                // Cleanup our socket
                this._clientSocket.Disconnect(false);
                this._clientSocket.Dispose();
            }
            catch (Exception e)
            {
                Console.WriteLine("Error Occured: " + e.Message);
            }
        }
示例#2
0
        /// <summary>
        /// Determine what server the server class has to connect to.
        /// It takes the algorithm and based on that it will choose the server
        /// </summary>
        /// <param name="cookie">Cookie if there is any otherwise it is null</param>
        /// <param name="session">Session if there is any otherwise it is null</param>
        /// <returns>Server object with connect information</returns>
        public string[] GetConnectionInfo(string cookie, string session)
        {
            int serverChosen = 0;

            switch (Algoritme.Get())
            {
            case "Random":
                Random rnd = new Random();
                serverChosen = rnd.Next(0, servers.Count);
                break;

            case "Round Robin":
                serverChosen = Algoritme.roundRobinPos;
                if (Algoritme.roundRobinPos != servers.Count - 1)
                {
                    Algoritme.roundRobinPos++;
                }
                else
                {
                    Algoritme.roundRobinPos = 0;
                }
                break;

            case "Load":
                // Chooses the server with the less Load. What is based on the current amount of connections to a server.
                serverChosen = 0;
                List <int> requestsServers = new List <int>();
                foreach (var serverRequest in Algoritme.requestPerServer)
                {
                    requestsServers.Add(Int32.Parse(serverRequest[1]));
                }

                var i = 0;
                foreach (var requestsServer in requestsServers)
                {
                    if (requestsServer == requestsServers.Min())
                    {
                        serverChosen = i;
                    }
                    i++;
                }
                break;

            case "Cookie Based":
                var j = 0;
                foreach (var server in servers)
                {
                    if (server.ToString().Split('/')[2] == cookie)
                    {
                        serverChosen = j;
                    }
                    j++;
                }
                break;

            case "Session Based":
                var sessions = Algoritme.sessionsPerServer;

                // If there is no session set yet it will choose a server based on Round Robin
                if (session == null)
                {
                    serverChosen = Algoritme.roundRobinPos;
                    if (Algoritme.roundRobinPos != servers.Count - 1)
                    {
                        Algoritme.roundRobinPos++;
                    }
                    else
                    {
                        Algoritme.roundRobinPos = 0;
                    }
                }
                // There is a session
                else
                {
                    // Check if the session is already stored in our list of stored sessions
                    var    isAlreadyStored = false;
                    object selectedServer  = null;

                    foreach (var stringse in Algoritme.sessionsPerServer)
                    {
                        if (session == stringse[0])
                        {
                            isAlreadyStored = true;
                            selectedServer  = stringse[1];
                        }
                    }

                    if (isAlreadyStored)
                    {
                        // The session is already stored
                        var l = 0;
                        foreach (var server in servers)
                        {
                            if (server == selectedServer)
                            {
                                serverChosen = l;
                            }
                            l++;
                        }
                    }
                    else
                    {
                        // Session is not stored yet
                        // Add new session id to the local storage
                        var      k = 0;
                        string[] sessionPerServer = null;
                        if (Algoritme.roundRobinPos != 0)
                        {
                            Algoritme.roundRobinPos--;
                        }
                        else
                        {
                            Algoritme.roundRobinPos = servers.Count - 1;
                        }

                        foreach (var server in servers)
                        {
                            if (k == Algoritme.roundRobinPos)
                            {
                                sessionPerServer = new string[] { session, server.ToString() };
                            }
                            k++;
                        }
                        serverChosen = Algoritme.roundRobinPos;
                        Algoritme.sessionsPerServer.Add(sessionPerServer);
                    }
                }
                break;
            }
            // Keep track of the requests for health monitoring
            HealthMonitor.addConnection(serverChosen);

            // Return the connectInfo to the server class
            var connectInfo = GetHostAndPort(servers[serverChosen] as string);

            return(connectInfo);
        }