自定義web伺服器(四)

發表於2013-06-25

   關於HTTP協議的具體內容,前面章節已經有所講解,相信讀者已有所瞭解,在此不在累述,本章節講解自定義web伺服器。

 一,.net提供自定義Web伺服器的類

      以下只是寫主要的類

      1.HTTPListener:對TCPListener的封裝

      2.TCPListener:對Socket的封裝

      3.Socket:對協議棧傳輸層介面的封裝

 二,用.net提供的類進行web伺服器的自定義

     1.用HTTPListener

using System;
using System.Net;
using System.IO;
using System.Text;
using System.Globalization;
using System.Threading;

namespace Microsoft.Samples.HttpListener
{
    static class HttpRequestListener
    {
        public static void Main()
        {
            string[] prefixes = new string[1];
            prefixes[0] = "http://localhost:8080/";
            ProcessRequests(prefixes);
        }


        private static void ProcessRequests(string[] prefixes)
        {
            if (!System.Net.HttpListener.IsSupported)
            {
                Console.WriteLine(
                    "Windows XP SP2, Server 2003, or higher is required to " +
                    "use the HttpListener class.");
                return;
            }
            // URI prefixes are required,
            if (prefixes == null || prefixes.Length == 0)
                throw new ArgumentException("prefixes");

            // Create a listener and add the prefixes.
            System.Net.HttpListener listener = new System.Net.HttpListener();
            Thread handleRequest = null;
            foreach (string s in prefixes)
            {
                listener.Prefixes.Add(s);
            }

            try
            {
                // 啟動監聽,開始監聽請求
                listener.Start();
                Console.WriteLine("Listening...");

              while(true)
              {
                    HttpListenerResponse response = null;
                    
                        //  GetContext 在等待一個請求時將阻塞 .
                        HttpListenerContext context = listener.GetContext();

                       
                        handleRequest = new Thread(delegate()
                        {
                            try
                            {
                                Console.WriteLine("當前執行緒是否為執行緒池執行緒:" + (Thread.CurrentThread.IsThreadPoolThread==true?"":""));
                               Console.WriteLine("當前執行緒總數:" + System.Diagnostics.Process.GetCurrentProcess().Threads.Count.ToString());
                            response = context.Response;

                            string responseBody =
                                "<HTML><head><script language='javascript' type='text/javascript'>function test(){alert('你好');}</script></head><BODY><form>The time is currently " + DateTime.Now.ToString() + "<br/>";
                            responseBody += "<input type='button' value='js測試' id='test1' onclick='test();'/><br/><input type='submit' value='提交測試' id='test2' /></form></BODY></HTML>";
                            string responseHeader =
                         string.Format(
                             "Content-Type: text/html; charset=UTf-8;Content-Length: {0}", responseBody.Length);

                            byte[] responseBodyBytes = Encoding.UTF8.GetBytes(responseBody);
                            response.ContentLength64 = responseBodyBytes.Length;
                            System.IO.Stream output = response.OutputStream;
                            // 向客戶端傳送迴應頭資訊
                            response.Headers.Add(responseHeader);
                            // 向客戶端傳送狀態行
                            response.StatusCode = (int)HttpStatusCode.OK;
                            response.ProtocolVersion = Version.Parse("1.1");
                            // 想客戶端傳送主體部分
                            output.Write(responseBodyBytes, 0, responseBodyBytes.Length);
                            }
                            catch (HttpListenerException ex)
                            {
                               Console.WriteLine(ex.Message);
                             }
                            finally
                            {
                              if (response != null)
                                response.Close();
                            }
                            Thread.Sleep(100000);
                        });
                        handleRequest.Start();
                    }
            }
            catch (HttpListenerException ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                //停止監聽
                listener.Close();
                Console.WriteLine("Done Listening.");
            }
        }
    }
}
View Code

         服務端執行效果:

        

         客戶端執行效果:

        

     2.用TCPListener

  private static void  ProcessRequestsWithTcpListener()
       {
           TcpListener server=new TcpListener(IPAddress.Any,8081);
       
           server.Start();

           Console.WriteLine("HTTP Server Start Listening....");

           while (true)
           {
               TcpClient client = server.AcceptTcpClient();
               Thread handleRequest = new Thread(delegate()
               {
                   try
                   {
                       NetworkStream inputoutputstream = client.GetStream();
                       Byte[] buffer = new Byte[1024];
                       int readLength = inputoutputstream.Read(buffer, 0, buffer.Length);
                       String inputoutputstring = Encoding.ASCII.GetString(buffer, 0, readLength);

                       Console.WriteLine("客戶端資訊:" + client.Client.RemoteEndPoint);
                       Console.WriteLine("客戶端請求資訊:\n" + inputoutputstring);

                       String statusLine = "HTTP/1.1 200 OK\r\n";
                       string responseBody =
                                   "<HTML><head><script language='javascript' type='text/javascript'>function test(){alert('你好');}</script></head><BODY><form>The time is currently " + DateTime.Now.ToString() + "<br/>";
                       responseBody += "<input type='button' value='js測試' id='test1' onclick='test();'/><br/><input type='submit' value='提交測試' id='test2' /></form></BODY></HTML>";
                       string responseHeader =
                           string.Format(
                               "Content-Type: text/html; charset=UTf-8\r\nContent-Length: {0}\r\n", responseBody.Length + statusLine.Length);
                       byte[] responseStatusLineBytes = Encoding.UTF8.GetBytes(statusLine);
                       byte[] responseHeaderBytes = Encoding.UTF8.GetBytes(responseHeader);
                       byte[] responseBodyBytes = Encoding.UTF8.GetBytes(responseBody);

                       // 寫入狀態行資訊
                       inputoutputstream.Write(responseStatusLineBytes, 0, responseStatusLineBytes.Length);
                       // 寫入迴應的頭部
                       inputoutputstream.Write(responseHeaderBytes, 0, responseHeaderBytes.Length);
                       // 寫入迴應頭部和內容之間的空行
                       inputoutputstream.Write(new byte[] { 13, 10 }, 0, 2);

                       // 寫入迴應的內容
                       inputoutputstream.Write(responseBodyBytes, 0, responseBodyBytes.Length);
                   }
                   catch (Exception ex)
                   {
                       Console.WriteLine("異常資訊:"+ex.Message);
                   }
                   finally
                   {
                       // 關閉與客戶端的連線
                       client.Close();
                   }

               });
               handleRequest.Start();
           }
       }
View Code

        服務端執行效果:

     

        客戶端執行效果:和1類似

      3.用Socket

 private static void ProcessRequestsWithSocket()
        {
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            server.Bind(new IPEndPoint(IPAddress.Any, 8082));
            server.Listen(100);

            Console.WriteLine("HTTP Server Start Listening....");

            while (true)
            {
                Socket client = server.Accept();
                Thread handleRequest = new Thread(delegate()
                {
                    try
                    {
                        Byte[] buffer = new Byte[1024];
                        int readLength = client.Receive(buffer, buffer.Length,SocketFlags.None);
                        String inputoutputstring = Encoding.ASCII.GetString(buffer, 0, readLength);

                        Console.WriteLine("客戶端資訊:" + client.RemoteEndPoint);
                        Console.WriteLine("客戶端請求資訊:\n" + inputoutputstring);

                        String statusLine = "HTTP/1.1 200 OK\r\n";
                        string responseBody =
                                    "<HTML><head><script language='javascript' type='text/javascript'>function test(){alert('你好');}</script></head><BODY><form>The time is currently " + DateTime.Now.ToString() + "<br/>";
                        responseBody += "<input type='button' value='js測試' id='test1' onclick='test();'/><br/><input type='submit' value='提交測試' id='test2' /></form></BODY></HTML>";
                        string responseHeader =
                            string.Format(
                                "Content-Type: text/html; charset=UTf-8\r\nContent-Length: {0}\r\n", responseBody.Length + statusLine.Length);
                        byte[] responseStatusLineBytes = Encoding.UTF8.GetBytes(statusLine);
                        byte[] responseHeaderBytes = Encoding.UTF8.GetBytes(responseHeader);
                        byte[] responseBodyBytes = Encoding.UTF8.GetBytes(responseBody);

                        // 寫入狀態行資訊
                        client.Send(responseStatusLineBytes);
                        // 寫入迴應的頭部
                        client.Send(responseHeaderBytes);
                        // 寫入迴應頭部和內容之間的空行
                        client.Send(new byte[] { 13, 10 });

                        // 寫入迴應的內容
                        client.Send(responseBodyBytes);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("異常資訊:" + ex.Message);
                    }
                    finally
                    {
                        // 關閉與客戶端的連線
                        client.Close();
                    }

                });
                handleRequest.Start();
            }
        }
View Code

        服務端和客戶端執行效果和2類似.
    宣告:2和3程式碼修改自:http://www.cnblogs.com/zhili/archive/2012/08/23/WebServer.html 只為交流,不為商用.

    備註:面試時,常問的一個問題是:http中post和get請求的區別

            個人感覺:1.兩者傳輸方式不同,post將資料放在請求內容裡傳輸,get放在請求行傳輸

                          2.post內容沒有大小限制,get內容有大小限制。

相關文章