編寫一個簡單的Web Server

編寫一個簡單的Web Server實際上是垂手可得的。若是咱們只是想託管一些HTML頁面,咱們能夠這麼實現:html

在VS2013中建立一個C# 控制檯程序web

 

編寫一個字符串擴展方法類,主要用於在URL中截取文件名瀏覽器

ExtensionMethods.cs服務器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace webserver1
{   
    /// <summary>
    /// 一些有用的字符串擴展方法
    /// </summary>
    public static class ExtensionMethods
    {   
        /// <summary>
        /// 返回給定字符串左側的字串或是整個源字符串
        /// </summary>
        /// <param name="src">源字符串</param>
        /// <param name="s">對比字符串</param>
        /// <returns></returns>
        public static string LeftOf(this String src, string s)
        {
            string ret = src;
            int idx = src.IndexOf(s);
            if (idx != -1) { ret = src.Substring(0, idx); }
            return ret;
        }

        /// <summary>
        /// 返回給定字符串右側的字串或是整個源字符串
        /// </summary>
        /// <param name="src">源字符串</param>
        /// <param name="s">對比字符串</param>
        /// <returns></returns>
        public static string RightOf(this String src, string s)
        {   
            string ret = String.Empty;
            int idx = src.IndexOf(s); 
            if (idx != -1) { 
                ret = src.Substring(idx + s.Length); 
            } return ret;
        }

    }
}

 

在入口程序中開啓HTTP監聽async

Program.csthis

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.IO;

namespace webserver1
{
    class Program
    {
        static Semaphore sem;

        static void Main(string[] args)
        {   
            //支持模擬20個鏈接
            sem = new Semaphore(20, 20);
            
            HttpListener listener = new HttpListener();
            string url = "http://localhost/";
            listener.Prefixes.Add(url);
            listener.Start();
            
            Task.Run(() =>
            {   
                while (true) {
                    sem.WaitOne();
                                        
                    StartConnectionListener(listener);
                }
            });

            Console.WriteLine("點擊任意鍵,退出WebServer");
            Console.ReadLine();
        }

        static async void StartConnectionListener(HttpListener listener)
        {
            // 等待鏈接。
            HttpListenerContext context = await listener.GetContextAsync();

            //釋放信號器,另一個監聽器能夠馬上開啓
            sem.Release();
            
            //得到請求對象
            HttpListenerRequest request = context.Request;
            HttpListenerResponse response = context.Response;
            // 在URL路徑上截取文件名稱, 介於 "/" 和 "?"之間
            string path = request.RawUrl.LeftOf("?").RightOf("/");
            Console.WriteLine(path);
            //輸出一些內容
            try
            {   
                // 加載文件並以UTF-8的編碼返回
                string text = File.ReadAllText(path);
                byte[] data = Encoding.UTF8.GetBytes(text);
                response.ContentType = "text/html";
                response.ContentLength64 = data.Length;
                response.OutputStream.Write(data, 0, data.Length);
                response.ContentEncoding = Encoding.UTF8;

                response.StatusCode = 200;
                
                response.OutputStream.Close();
            }
            catch (Exception ex) { Console.WriteLine(ex.Message); }

        }
    }
}

上面的代碼初始化了20個監聽器。 採用信號器(Semaphore),當一個請求收到後,釋放一個信號器,一個新的監聽器再次被建立。這個服務器能夠同時接收20個請求。使用await機制來處理線程是否繼續運行。若是你不熟悉Task、async/await的使用,建議參考一些文檔。編碼

 

建立一個HTML文件,並把屬性{複製到輸入目錄}設置爲 「若是較新則複製」url

 index.htmlspa

<html>
<head>
    <title>Simple WebServer</title>
</head>
<body>
    <p>Hello World</p>
</body>
</html>

 

整個目錄結構線程

 

運行控制檯程序,在瀏覽器中輸入地址:

http://localhost/index.html

  

若是瀏覽器沒法訪問localhost,編輯C:\Windows\System32\drivers\etc\hosts文件,保證有一條這樣的記錄

127.0.0.1 localhost

 代碼下載

相關文章
相關標籤/搜索