/// <summary> /// Passes the given response message to the endpoint. /// </summary> /// <param name="response"></param> public void PassResponse(ProxyMessage response, Socket clientSocket) { // Send the response to the client if (clientSocket != null && clientSocket.Connected) { clientSocket.Send(response.Content); } }
/// <summary> /// Passes the given client message to the given endpoint. /// </summary> /// <param name="message">The message of the client and his endpoint.</param> /// <param name="dstEP">The endpoint that will receive the client's message</param> public void PassClientMessage(ProxyMessage message, IPEndPoint dstEP) { // Build the message in our proxy format: // <endpoint_bytes><client_message> var ipBytes = message.ClientEndpoint.Address.GetAddressBytes(); var portBytes = BitConverter.GetBytes(message.ClientEndpoint.Port).Take(PORT_LENGTH_IN_BYTES).ToArray(); byte[] messageToSend = ipBytes.Concat(portBytes).Concat(message.Content).ToArray(); // Send the proxy-formatted message to the destination Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp); try { socket.Connect(dstEP); } catch { throw new Exception("Connection to server failed."); } socket.Send(messageToSend); }
static void Main(string[] args) { // Load all the servers from the configuration file in a constant interval Thread serverLoadingThread = new Thread(() => { while (true) { HashSet <IPEndPoint> addedServers = LoadServers(SERVERS_FILE); //Console.WriteLine("Reloading servers..."); // Add the new servers to the Load Balancer foreach (var server in addedServers) { lock (_loadBalancer) { _loadBalancer.AddLoadCarrier(server); } } // Sleep for ten Seconds Thread.Sleep(SECOND); } }); serverLoadingThread.Start(); // Start the status-printing thread Thread statusPrintingThread = new Thread(() => { while (true) { PrintLoadBalancingStatus(); Thread.Sleep(100); } }); statusPrintingThread.Start(); // Set-up the server and start listening for client-requests and server-responses ProxyServer proxyServer = new ProxyServer(SERVE_PORT, PROXY_PORT); proxyServer.Start(); while (true) { // Get request from client ProxyMessage clientRequest = proxyServer.ReceiveClientMessage(); _clients[clientRequest.ClientEndpoint] = clientRequest.Socket; //ColorizedWriteLine($"REQUEST from {clientRequest.ClientEndpoint}", ConsoleColor.Green); // Pick the most available server IPEndPoint handlingServer; lock (_loadBalancer) { //Console.WriteLine("Picking Web Server..."); handlingServer = _loadBalancer.PickMostAvailableCarrier(); //Console.WriteLine($"Picked {handlingServer}"); } try { // Pass the request of the client to the server //Console.WriteLine($"Passing Client Request to {handlingServer}"); proxyServer.PassClientMessage(clientRequest, handlingServer); // Add the load to the handling server _loadBalancer.AddLoad(handlingServer); } catch // There's a problem with the web server { // Send the client an error message byte[] problemResponseData = Encoding.ASCII.GetBytes("HTTP/1.1 500 Internal Server Error"); var clientEP = clientRequest.ClientEndpoint; proxyServer.PassResponse(new ProxyMessage(clientEP, null, problemResponseData), clientRequest.Socket); // Remove the load from the handling server _loadBalancer.RemoveLoad(handlingServer); // Notify in the console that the web server has a problem ColorizedWriteLine($"Web Server {handlingServer} has a problem! (2)", ConsoleColor.Red); continue; } // Queue a thread for handling the request ThreadPool.QueueUserWorkItem((obj) => { try { // Get the response for the client form the server ProxyMessage serverResponse = proxyServer.ReceiveResponse(); // Pass the response to the client proxyServer.PassResponse(serverResponse, _clients[serverResponse.ClientEndpoint]); _clients.Remove(serverResponse.ClientEndpoint); //ColorizedWriteLine($"RESPONSE to {clientRequest.ClientEndpoint}", ConsoleColor.Blue); } catch (Exception e) { // Send the client an error message byte[] problemResponseData = Encoding.ASCII.GetBytes("HTTP/1.1 500 Internal Server Error"); var clientEP = clientRequest.ClientEndpoint; proxyServer.PassResponse(new ProxyMessage(clientEP, null, problemResponseData), clientRequest.Socket); // Notify in the console that the web server has a problem ColorizedWriteLine($"Web Server {handlingServer} has a problem!\n", ConsoleColor.Red); } // Remove the load from the handling server _loadBalancer.RemoveLoad(handlingServer); }); } }