【Web後端筆記】基於Socket實現的簡單Web伺服器搭建

來源:互聯網
上載者:User

標籤:style   blog   http   io   color   os   ar   使用   for   

我們在地址欄中輸入的內容稱為通用資源標記符(Universal Resource Identifier,URI)它有很多種樣式,在Web中我們通常稱為統一資源定位器(Uniform Resource Locator,URL)的形式,它的格式如下: 

      協議://主機[.連接埠號碼][絕對路徑[?參數]] 

      在http://www.cnblogs.com/DebugLZQ/中,http表示協議名稱;www.cnblogs.com表示主機的地址;可選的連接埠號碼沒有出現,那麼,將使用http協議預設的連接埠號碼80;絕對路徑為/DebugLZQ/;在這個例子中沒有參數出現。

      在.NET中,不管是URI還是URL,都使用定義在System命名空間中得URI類來進行處理。對應上面的介紹,這個類定義了5個屬性,分別對應5個組成部分,如下所示:

    Scheme:協議的名稱

    Host:取得URI地址中得主機部分

    Port:取得連接埠號碼

    AbsolutePath:絕對路徑部分

    Query:URI地址中得參數部分

      下面的例子示範了地址中各個部分:

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5   6 namespace URI說明 7 { 8     class Program 9     {10         static void Main(string[] args)11         {12             System.Uri DebugLZQAddress = new Uri("http://www.cnblogs.com/DebugLZQ/");13             Console.WriteLine("Scheme: {0}",DebugLZQAddress.Scheme );14             Console.WriteLine("Host: {0}", DebugLZQAddress.Host );15             Console.WriteLine("Port: {0}", DebugLZQAddress.Port );16             Console.WriteLine("AbsolutePath: {0}", DebugLZQAddress.AbsolutePath );17             Console.WriteLine("Query: {0}", DebugLZQAddress.Query );18         }19     }20 }

輸出結果如下:

其中絕對路徑部分使用類似於Unix的檔案目錄的形式來描述伺服器中得資源,這個絕對路徑被傳送到伺服器之後,在Web伺服器上通常被稱為虛擬路徑。

      我們在地址欄輸入URL後,如何找到伺服器呢?互連網上的主機千千萬,我們要訪問的伺服器是互連網上數千萬台伺服器中得一台,它很可能遠在地球的另一邊。瀏覽器要找到伺服器,需要提供伺服器的網路地址。

      在當前的TCP/IP協議下,所謂伺服器的網路地址,就是一個IP地址,目前我們使用IPv4的地址,即IP協議第4個版本規定的地址,每個地址由四個位元組共32位組成。理論上將,可以表示4G個網路地址。通常我們用遠點分隔四個數字來表示一個地址,每個數字對應地址的一個位元組,例如,微軟的IP地址為:207.46.19.254,直接在地址欄中輸入http://207.46.19.254也可以訪問網頁。

      但是,這些數字實在很難讓人記憶,人們更願意通過一個有意義的名字來找到一台主機。在經曆了短暫得互連網初期階段之後,1983年,保羅·莫卡派(Paul Mockapetris)發明了網域名稱系統,這樣,在互連網上,我們可以為IP地址起一個有意義的名字以方便找尋主機,這個名字成為網域名稱。比如,微軟Web伺服器的網域名稱為www.microsoft.com,這個名字對應實際IP地址為207.46.19.254。

      雖然這個名字很好記,但是只有這個名字並不能直接找到微軟的Web伺服器,必須建立起名字和IP地址之間的對應關係。這個工作由網域名稱伺服器DNS(即Domain Name Server)完成。DNS伺服器提供一個列私語分層的通訊錄,允許使用者通過網域名稱來尋找對應的地址,或者完成通過地址來尋找對應的網域名稱。通常情況下,互連網服務商已經為我們自動化佈建了DNS伺服器,因此可以簡單地通過www.microsoft.com網域名稱找到微軟的Web伺服器。

      找到伺服器之後,需要將請求從我們的用戶端傳輸到伺服器,那麼,兩台電腦是如何通訊的呢?他們如何才能理解彼此發送的資料呢?這就需要提到協議。

      當瀏覽器尋找到Web伺服器的地址之後,瀏覽器協助我們把對伺服器的請求轉換為一系列參數發送給Web伺服器。伺服器受到瀏覽器發來的請求參數之後,將會分析這些資料,並進行處理。然後向瀏覽器回應處理的結果,也就是一些新的資料;這些資料通常是HTML網頁或者圖片。瀏覽器收到之後,解析這些資料,將它們呈現在瀏覽器的視窗中,這就是我們看到的網頁。

      在瀏覽器與Web伺服器的對話中,需要使用雙方都能夠理解的文法規範進行通訊,這種程式之間進行通訊的文法規範,我們稱之為協議。協議有許多種,根據國際標準組織ISO的網路參考模型,程式與程式之間的通訊可分為7層,從低到高依次為:物理層、資料連結層、網路層、傳輸層、會話層、展示層、應用程式層。每層都有自己對應的協議。比如,應用程式層之間的協議我們稱之為應用程式層協議。不同的應用程式可能有著不同的應用程式層協議。同一層的協議也可能有很多種。

瀏覽器與Web伺服器之間的協議是應用程式層協議,當前,我們主要遵循的協議為HTTP/1.1。HTTP協議是Web開發的基礎,這是一個無狀態的協議,客戶機與伺服器之間通過請求和相應完成一次會話(Session)。每次會話中,通訊雙方發送的資料稱為訊息(Message),訊息分兩種:請求訊息和回應訊息。

      訊息的格式。

 圖DebugLZQ用繪圖畫的,不太美觀。吼吼。。。 博友心聲:真醜。。。    

      每個訊息可能由三部分組成,第一部分為請求行或者回應的狀態行,第二部分為訊息的頭部,第三部分為訊息體部分。訊息頭部分和訊息體部分使用一個空行進行分隔。

      通常情況下,我們在用戶端使用瀏覽器來訪問伺服器,瀏覽器軟體協助我們構造所有的請求訊息。使用Fiddler軟體,可以協助我們檢測到瀏覽器與伺服器之間的通訊內容,。

右上部為瀏覽器請求的內容,可以看到,第一行為請求行,請求的內容為:

      GET http://www.microsoft.com/en-us/default.aspx HTTP/1.1

      下面的連續N行為要求標頭部分,然後是一個空行,由於是GET請求,所以沒有請求體部分。

      圖右下部為伺服器回應的內容,第一行為回應的狀態行,HTTP/1.1 200 OK表示請求的內容可以找到,但是需要到另外的地址去取。下面的15行為回應的頭部。一個空行分隔了回應的頭部和回應體部分,回應體中為一個簡單的HTML網頁。

      HTTP協議定義了內容的格式,這是一個應用程式層的協議,應用程式層協議的內容需要通過傳輸層在瀏覽器和伺服器之間傳送,TCP/IP協議是ISO網路參考模型的一種實現。在TCP/IP協議中,與網路程式員相關的主要有兩層:傳輸層和應用程式層。

      傳輸層協議負責解決資料轉送問題,包括資料通行的可靠性問題。傳輸層依賴更底層的網路層來完成實際的資料轉送,在TCP/IP網路通訊協定中,負責可靠通訊的傳輸層協議為TCP協議。而網路層一般用網路驅動來實現,普通的程式員不會涉及;在TCP/IP協議中,網路層的協議為IP協議。

      應用程式層用於在特定的應用程式之間傳輸資料。HTTP協議就是TCP/IP協議中專門用於瀏覽器與Web伺服器之間通訊的應用程式層協議。應用程式層協議依賴於傳輸層協議完成資料轉送,傳輸層協議依賴於網路層協議王城資料轉送,他們之間的關係如(瀏覽器與伺服器之間網路通訊的傳輸過程):

到這裡,我們的準備理論超不讀了,哦,還得再認識下Socket。

      在遙遠的Unix時代,為瞭解決傳輸層的編程問題,從4.2BSD Unix開始,Unix提供了類似於檔案操作的網路操作方式----Socket。通過Socket,程式員可以像檔案一樣通過開啟、寫入、讀取、關閉等操作完成網路編程。這使得網路編程可以統一到檔案操作之下。通過Socket協助程式員解決網路傳輸層的問題,而系統中得網路系統負責處理網路內部的複雜操作,這樣程式員就可以比較容易地編寫網路應用程式。需要注意的是應用程式層的協議需要針對網路程式專門處理,Socket不負責應用程式層的協議,僅僅負責傳輸層的協議。

      當然網路畢竟不是簡單的檔案,所以,在使用Socket的時候,程式員還是需要設定一些網路相關的細節問題參數。

      當通過Socket開發網路應用程式的時候,首先需要考慮所使用的網路類型,主要包括以下三個方面:

    1)Socket類型,使用網路通訊協定的類別,如IPv4的類型為PF_INET。

    2)資料通訊的類型,常見的資料報(SOCK_DGRAM)、資料流(SOCK_STREAM)。

    3)使用的網路通訊協定,比如:TCP協議。

      在同一個網路地址上,為了區分使用相同協議的不同應用程式,可以為不同的應用程式分配一個數字編號,這個編號稱為網路連接埠號碼(port)。連接埠號碼是一個兩位元組的認證,取值範圍從0~65535。IANA(Internet Assigned Number Authority,互連網地址分配機構)維護了一個連接埠分配列表,這些連接埠分三類,第一類的範圍是0~1023,稱為眾所周知的連接埠,由IANA進行控制和分配,由特定的網路程式使用,例如,TCP協議使用80號連接埠來完成HTTP協議的傳輸。第二類的範圍是1024~49151,稱為登記連接埠,這些連接埠不由IANA控制,但是IANA委會了一個登記的列表,如果沒有在IANA登記的話,也不應該在程式中使用。但是大多數的系統中,在沒有衝突的情況下,也可以有使用者程式使用。第三類的範圍是49152~65535,稱為動態或者似有連接埠號碼,這些連接埠可以由普通使用者程式使用。

      對於一個網路應用程式來說,通過地址、協議和連接埠號碼可以唯一地確定網路上的一個應用程式。其中地址和連接埠的組合稱為端點(EndPoint)。每個Socket需要綁定到一個端點上與其他端點進行通訊。

      在.NET中,System.Net命名空間提供了網路編程的大多數資料類型以及常用操作,其中常用的類型如下:

    1)IPAddress類用來表示一個IP地址。

    2)IPEndPoint類用來表示一個IP地址和一個連接埠號碼的組合,稱為網路的端點。

    3)System.Net.Sockets命名空間中提供了基於Socket編程的資料類型。

    4)Socket類封裝了Socket的操作。

      常用的操作如下:

    1)Listen:設定基於串連通訊的Socket進入堅挺狀態,並設定等待隊列的長度。

    2)Accept:等待一個新的串連,當新串連到達的時候,返回一個指標對新串連的Socket對象。通過新的Socket對象,可以與新串連通訊。

    3)Receive:通過Socket接受位元組資料,儲存到一個位元組數組中,返回實際接受的位元組數。

    4)Send:通過Socket發送預先儲存在位元組數組中得資料。

      博友聲音:夠了,說了這麼多,DebugLZQ真是不嫌麻煩。。。快!!!!!

      DebugLZQ:吼吼,有了上面的基礎,下面用代碼示範如何通過Socket編程建立一個簡單的Web伺服器。必要說明:這個伺服器通過49152號連接埠提供訪問,向瀏覽器返回一個固定的靜態網頁。在這個解決方案中,請求的訊息由瀏覽器產生,並發送到伺服器,這個程式將簡單地顯示請求資訊。回應的訊息由伺服器程式產生,通過Socket傳輸層返回給瀏覽器。

 

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net;// 6 using System.Net.Sockets;// 7   8 namespace 基於Socket的最簡單Web伺服器 9 {10     class Program11     {12         static void Main(string[] args)13         {14             IPAddress address = IPAddress.Loopback;//取得原生loopback網路地址,即127.0.0.115             IPEndPoint endPoint = new IPEndPoint(address, 49152);//建立可訪問的端點,49152表示連接埠號碼,如果設定為0,表示使用一個閒置連接埠號碼16             Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//建立socket,使用IPv4地址,資料通訊類型為位元組流,TCP協議17             socket.Bind(endPoint);//將socket綁定到一個端點上18             socket.Listen(10);//設定串連隊列的長度19             Console.WriteLine("開始監聽,連接埠號碼:{0}",endPoint.Port );20             while (true)21             {22                 Socket client = socket.Accept();//開始監聽,這個方法會阻塞線程的執行,直到接受到一個用戶端的請求串連23                 Console.WriteLine(client.RemoteEndPoint);//輸出用戶端的地址24                 byte[] buffer = new byte[4096];//準備讀取用戶端請求的資料,讀取的資料將儲存在一個數組中25                 int length = client.Receive(buffer, 4096, SocketFlags.None);//接受資料26                 //將請求資料翻譯為UTF-827                 System.Text.Encoding utf8 = System.Text.Encoding.UTF8;28                 string requestString = utf8.GetString(buffer, 0, length);29                 Console.WriteLine(requestString);//顯示請求30                 //回應的狀態行31                 string statusLine = "HTTP/1.1 200 OK\r\n";32                 byte[] statusLineBytes = utf8.GetBytes(statusLine);33                 //準備發送回用戶端的網頁34                 string responseBody = "<html><head><title>From Socket Server</title></head><body><h1>Hello world.<h1></body></html>";35                 byte[] responseBodyBytes = utf8.GetBytes(responseBody);36                 //回應的頭部37                 string responseHeader = string.Format("Content-Type:text/html;charset=UTF-8\r\nContent-Length:{0}\r\n",responseBody.Length );38                 byte[] responseHeaderBytes = utf8.GetBytes(responseHeader);39  40                 //向用戶端發送狀態資訊41                 client.Send(statusLineBytes);42                 //向用戶端發送回應頭43                 client.Send(responseHeaderBytes);44                 //頭部與內容的分隔行45                 client.Send(new byte[]{13,10});46                 //向用戶端發送內容部分47                 client.Send(responseBodyBytes);48  49                 //斷開與用戶端的串連50                 client.Close();51                 if (Console.KeyAvailable)52                     break;53             }54             socket.Close();55         }56     }57 }

運行後,在瀏覽器的視窗中輸入:http://localhost:49152/,瀏覽器中可以看到如下的顯示結果。

在命令列中看到如下輸出:

參考原文:http://www.cnblogs.com/DebugLZQ/archive/2011/12/06/2278234.html

【Web後端筆記】基於Socket實現的簡單Web伺服器搭建

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.