Multi-threading with .Net HttpListener

后端 未结 5 1571
盖世英雄少女心
盖世英雄少女心 2020-12-02 07:33

I have a listener:

listener = new HttpListener();
listener.Prefixes.Add(@\"http://+:8077/\");
listener.Start();
listenerThread = new Thread(HandleRequests);
         


        
5条回答
  •  一向
    一向 (楼主)
    2020-12-02 08:19

    This uses the BlockingCollection typed queue to service requests. It is usable as is. You should derive a class from this one and override Response.

    using System;
    using System.Collections.Concurrent;
    using System.Net;
    using System.Text;
    using System.Threading;
    
    namespace Service
    {
        class HttpServer : IDisposable
        {
            private HttpListener httpListener;
            private Thread listenerLoop;
            private Thread[] requestProcessors;
            private BlockingCollection messages;
    
            public HttpServer(int threadCount)
            {
                requestProcessors = new Thread[threadCount];
                messages = new BlockingCollection();
                httpListener = new HttpListener();
            }
    
            public virtual int Port { get; set; } = 80;
    
            public virtual string[] Prefixes
            {
                get { return new string[] {string.Format(@"http://+:{0}/", Port )}; }
            }
    
            public void Start(int port)
            {
                listenerLoop = new Thread(HandleRequests);
    
                foreach( string prefix in Prefixes ) httpListener.Prefixes.Add( prefix );
    
                listenerLoop.Start();
    
                for (int i = 0; i < requestProcessors.Length; i++)
                {
                    requestProcessors[i] = StartProcessor(i, messages);
                }
            }
    
            public void Dispose() { Stop(); }
    
            public void Stop()
            {
                messages.CompleteAdding();
    
                foreach (Thread worker in requestProcessors) worker.Join();
    
                httpListener.Stop();
                listenerLoop.Join();
            }
    
            private void HandleRequests()
            {
                httpListener.Start();
                try 
                {
                    while (httpListener.IsListening)
                    {
                        Console.WriteLine("The Linstener Is Listening!");
                        HttpListenerContext context = httpListener.GetContext();
    
                        messages.Add(context);
                        Console.WriteLine("The Linstener has added a message!");
                    }
                }
                catch(Exception e)
                {
                    Console.WriteLine (e.Message);
                }
            }
    
            private Thread StartProcessor(int number, BlockingCollection messages)
            {
                Thread thread = new Thread(() => Processor(number, messages));
                thread.Start();
                return thread;
            }
    
            private void Processor(int number, BlockingCollection messages)
            {
                Console.WriteLine ("Processor {0} started.", number);
                try
                {
                    for (;;)
                    {
                        Console.WriteLine ("Processor {0} awoken.", number);
                        HttpListenerContext context = messages.Take();
                        Console.WriteLine ("Processor {0} dequeued message.", number);
                        Response (context);
                    }
                } catch { }
    
                Console.WriteLine ("Processor {0} terminated.", number);
            }
    
            public virtual void Response(HttpListenerContext context)
            {
                SendReply(context, new StringBuilder("NULLThis site not yet implementd.") );
            }
    
            public static void SendReply(HttpListenerContext context, StringBuilder responseString )
            {
                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString.ToString());
                context.Response.ContentLength64 = buffer.Length;
                System.IO.Stream output = context.Response.OutputStream;
                output.Write(buffer, 0, buffer.Length);
                output.Close();
            }
        }
    }
    

    This is a sample of how to use it. No need to use events or any lock blocks. The BlockingCollection solves all these problems.

    using System;
    using System.Collections.Concurrent;
    using System.IO;
    using System.Net;
    using System.Text;
    using System.Threading;
    
    namespace Service
    {
      class Server
      {
        public static void Main (string[] args)
        {
            HttpServer Service = new QuizzServer (8);
            Service.Start (80);
            for (bool coninute = true; coninute ;)
            {
                string input = Console.ReadLine ().ToLower();
                switch (input)
                {
                    case "stop":
                        Console.WriteLine ("Stop command accepted.");
                        Service.Stop ();
                        coninute = false;
                        break;
                    default:
                        Console.WriteLine ("Unknown Command: '{0}'.",input);
                        break;
                }
            }
        }
      }
    }
    

提交回复
热议问题