Web Server - различни решения

Сървърът от лаба и Handmade smileyсървърът  НЕ работят асинхронно -поне при мен.

Тествам с Firefox Developer Edition yes има измерване на времето за отговор.

Това е кода от лекцията, по същият начин е на презентацията. Така е и на предната инстанция. 

На презентацията слагат Task.Wait()  в Main - така се блокира приложението и изобщо сърърът не може друго да прави

( например Console.ReadLine();)

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

public class Program
{
    static void Main(string[] args)
    {
        IPAddress address = IPAddress.Parse("127.0.0.1");
        int port = 8081;

        TcpListener tcpListener = new TcpListener(address, port);
        tcpListener.Start();

        Console.WriteLine($"Listening to TCP clients at 127.0.0.1:{port}");

        Task.Run(async () => await Connect(tcpListener));

        Console.ReadLine();
    }

    public static async Task Connect(TcpListener tcpListener)
    {
        Console.WriteLine("Waiting for client...");

        while (true)
        {
            TcpClient client = await tcpListener.AcceptTcpClientAsync();

            Console.WriteLine("Client connected.\n");

            byte[] buffer = new byte[1024];

            await client.GetStream().ReadAsync(buffer, 0, buffer.Length);

            string message = Encoding.ASCII.GetString(buffer);

            Console.WriteLine(message);

            byte[] response = Encoding.ASCII.GetBytes("<body><h1>Hello from server!</h1></body>");

            await Task.Delay(5000);

            await client.GetStream().WriteAsync(response, 0, response.Length);

            Console.WriteLine("Closing connection");

            client.GetStream().Dispose();
        }
    }
}

Полезно обяснение за async await. http://zpbappi.com/using-csharp-async-and-await-properly/

Така и не успях да го подкарам асинхронно.

От тук взех сървър, който работи асинхронно и използва HttpListener.

Добавих Delay за 5 сек. и като пусна няколко заявки всички минават за 5 секунди, а не се изчакват.

using System;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace HttpServer
{
    public static class Server
    {              
        public static int maxSimultaneousConnections = 20;
        private static Semaphore sem = new Semaphore(maxSimultaneousConnections, maxSimultaneousConnections);
        
        private static HttpListener InitializeListener()
        {
            HttpListener listener = new HttpListener();

            listener.Prefixes.Add("http://127.0.0.1:8081/");

            Console.WriteLine("Listening on IP 127.0.0.1:8081");
            
            return listener;
        }

        private static void StartListener(HttpListener listener)
        {
            listener.Start();
            Task.Run(() => RunServer(listener));
        }

        public static void Start()
        {
            HttpListener listener = InitializeListener();
            StartListener(listener);
        }

        private static void RunServer(HttpListener listener)
        {
            while (true)
            {
                sem.WaitOne();
                StartConnectionListener(listener);
            }
        }

        private static async void StartConnectionListener(HttpListener listener)
        {
            // Wait for a connection. Return to caller while we wait.
            HttpListenerContext context = await listener.GetContextAsync();

            // Release the semaphore so that another listener can be immediately started up.
            sem.Release();

            // We have a connection, do something...
            string response = "Hello Browser!";
            byte[] encoded = Encoding.UTF8.GetBytes(response);
            context.Response.ContentLength64 = encoded.Length;
            await Task.Delay(5000);
            context.Response.OutputStream.Write(encoded, 0, encoded.Length);
            context.Response.OutputStream.Close();
        }        
    }
}

След дълго ровене в нета за C# Web Server излиза, че  се реализира основно с TCPListener и по-рядко с HTTPListener.

Предимства на HttpListener: HttpListener парсва HTTP хедърите и създава HTTP респонси.
Дава набор от класове, които са много подобни на тези в ASP.Net, които дават достъп до хедъри, кукита и  други.

Основен недостатък на HttpListener - когато клиентът и сървърът са на една машина производителността пада при изпращане на съобщения с голям размер на бодито.