1.統一資源标示符
1) 格式:協定://主機[.端口号][絕對路徑[?參數]],在Http://www.kencery.com/hyl/index/login中,http表示協定的名稱,www.kencery.com表示主機的位址,可選的端口号沒有出現,那麼,将使用http協定的預設端口号80,絕對路徑為:hyl/index/login,如果沒有提供絕對路徑,那麼,使用預設的絕對路徑/。
2) .NET中提供的對URL或者URI操作的方法代碼如下:
1 Uri uri = new Uri("https://www.kencery.com/hyl/index/login");
2 Console.WriteLine(uri.Scheme); //協定的名稱 輸出結果:https
3 Console.WriteLine(uri.Host); //取得Uri位址中的主機部分 輸出結果:www.kencery.com
4 Console.WriteLine(uri.Port); //端口号 輸出結果:80
5 Console.WriteLine(uri.AbsolutePath); //絕對路徑 輸出結果:/hyl/index/login
6 Console.WriteLine(uri.Query); //位址中的參數部分 輸出結果:
7 Console.ReadLine();
3) 浏覽器要找到我們通路的伺服器,需要提供伺服器的網絡位址,在目前的TCP/IP協定下,所謂的伺服器位址其實就是一個IP位址,目前我們使用的是IPV4的位址,每個位址由四個位元組共32位組成,理論上講,可以表示4G的網絡位址,微軟的IP位址是:207.46.19.254,是以我們直接在位址欄中輸入http://207.46.19.254也可以看到微軟的網站。
4)HTTP協定
1.當浏覽器尋找到Web伺服器的位址之後,浏覽器将幫助我們把對伺服器的請求轉換為一系列的參數發送給Web伺服器,伺服器收到浏覽器發來的請求參數之後,将會分析這些資料并進行處理,然後向浏覽器回應處理的結果,也就是一些新的資料,浏覽器收到之後,就會解析這些資料,并将他們顯示在浏覽器中。
2,在浏覽器與Web伺服器之間進行通信的時候,需要雙方都要能夠了解的規範進行通訊,這種程式之間進行通信的語言規範,我們稱之為協定,協定有許多種,根據國際标準化組織ISO的網絡參考模型,程式與程式之間的通信可以分為7種,從低到高依次是:實體層,資料鍊路層,網絡層,傳輸層,會話層,表示層,應用層,每層都有自己對應的協定。
3.請求微軟網站的請求資訊如圖所示:Http請求

2.最簡單的Web伺服器
2.1 網絡插座Socket
在Unix時代,為了解決傳輸層的程式設計問題,Unix提供了類似于檔案操作的網絡操作方式—Socket,通過Socket,開發人員可以像操作檔案一樣通過打開,寫入,讀取,關閉等操作來完成網絡程式設計,Socket不負責應用層的協定,僅僅負責傳輸層的協定。
當通過Socket開發網絡應用程式的時候,首先需要考慮所使用的網絡類型,主要包括以下三個方面:
1)Socket類型,使用網絡協定的類别,IPV4的類型為PF_INET
2)資料通信的類型,常見的資料報(Sock_DGRAM),資料流(SOCK_STREAM)。
3)使用網絡協定,比如:TCP協定。
2.2 在.NET中,System.Net命名空間提供了網絡程式設計的大多數資料類型以及常用操作,其中類型如下:
1) IPAddress類用來表示一個IP位址
2) IPEndPoint類用來表示一個IP位址和一個端口号的組合,成為網絡的端口。
3) System.NET.Sockets命名空間中提供了基于Socket程式設計的資料類型。
4) Socket類封裝了Socket的操作。常見的操作如下:
a) Listen:設定基于連接配接通信的Socket進入監聽狀态,并設定等待隊列的長度。
b) Accept:等待一個新的連接配接,當新連接配接到達的時候,傳回一個針對新連接配接的Socket對象。通過這個新的Socket對象,可與新連接配接通信。
c) Receive:通過Socket接收位元組資料,儲存到一個位元組數組中,傳回實際接收的位元組數。
d) Send:通過Socket發送預先儲存在位元組數組中的資料。
2.3 通過Socket程式設計建立一個簡單地Web伺服器
1 private static void Main(string[] args)
2 {
3 //取得本機的loopbakack網絡位址,即127.0.0.1
4 IPAddress address = IPAddress.Loopback;
5 //建立可以通路的端點,49152表示端口号,如果設定為0,表示使用一個空閑的端口号
6 IPEndPoint endPoint = new IPEndPoint(address, 49152);
7 //建立Socket,使用IPV4位址,傳輸控制協定TCP,雙向,可靠,基于連接配接的位元組流
8 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
9 //将Socket綁定到一個端口上
10 socket.Bind(endPoint);
11 //設定連接配接隊列的長度
12 socket.Listen(10);
13 Console.WriteLine("開始監聽:端口号:{0}", endPoint.Port);
14 while (true)
15 {
16 //開始監聽,這個方法會阻塞線程的執行,直到接收到一個用戶端的連接配接請求
17 Socket client = socket.Accept();
18 //輸出用戶端位址
19 Console.WriteLine("用戶端位址:{0}", client.RemoteEndPoint);
20 //準備讀取用戶端請求的位址,讀取的資料将儲存在一個數組中
21 byte[] buffer = new byte[4096];
22 //接收資料
23 int length = client.Receive(buffer, 4096, SocketFlags.None);
24 //将請求的資料翻譯成UTF-8
25 Encoding utf8 = Encoding.UTF8;
26 string requestString = utf8.GetString(buffer, 0, length);
27 //顯示請求的資訊
28 Console.WriteLine(requestString);
29 //回應的狀态行
30 string statusLine = "HTTP/1.1 200 OK\r\n";
31 byte[] statusLineBytes = utf8.GetBytes(statusLine);
32 //準備發送到用戶端的網頁
33 string responseBody =
34 "<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",
38 responseBody.Length);
39 byte[] responseHeaderBytes = utf8.GetBytes(responseHeader);
40 //向用戶端發送狀态資訊
41 client.Send(statusLineBytes);
42 //向用戶端發送回應頭
43 client.Send(responseBodyBytes);
44 //頭部和内容的分割行
45 client.Send(new byte[] {13, 10});
46 //向用戶端發送内容部分
47 client.Send(responseBodyBytes);
48 //斷開與用戶端的連結
49 client.Close();
50 if (Console.KeyAvailable)
51 {
52 break;
53 }
}
54 //關閉伺服器
55 socket.Close();
57 }
2.4 基于TcpListener的Web伺服器
為了簡化基于TCP協定的監聽程式,.NET在System.Net.Sockets命名空間中提供了TcpListener類,代碼如下:
1 private static void Main(string[] args)
2 {
3 //取得本機的loopbakack網絡位址,即127.0.0.1
4 IPAddress address = IPAddress.Loopback;
5 //建立可以通路的端點,49152表示端口号,如果設定為0,表示使用一個空閑的端口号
6 IPEndPoint endPoint = new IPEndPoint(address, 49152);
7 //建立Socket,使用IPV4位址,傳輸控制協定TCP,雙向,可靠,基于連接配接的位元組流
8 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
9 //将Socket綁定到一個端口上
10 socket.Bind(endPoint);
11 //設定連接配接隊列的長度
12 socket.Listen(10);
13 Console.WriteLine("開始監聽:端口号:{0}", endPoint.Port);
14 while (true)
15 {
16 //開始監聽,這個方法會阻塞線程的執行,直到接收到一個用戶端的連接配接請求
17 Socket client = socket.Accept();
18 //輸出用戶端位址
19 Console.WriteLine("用戶端位址:{0}", client.RemoteEndPoint);
20 //準備讀取用戶端請求的位址,讀取的資料将儲存在一個數組中
21 byte[] buffer = new byte[4096];
22 //接收資料
23 int length = client.Receive(buffer, 4096, SocketFlags.None);
24 //将請求的資料翻譯成UTF-8
25 Encoding utf8 = Encoding.UTF8;
26 string requestString = utf8.GetString(buffer, 0, length);
27 //顯示請求的資訊
28 Console.WriteLine(requestString);
29 //回應的狀态行
30 string statusLine = "HTTP/1.1 200 OK\r\n";
31 byte[] statusLineBytes = utf8.GetBytes(statusLine);
32 //準備發送到用戶端的網頁
33 string responseBody =
34 "<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",
38 responseBody.Length);
39 byte[] responseHeaderBytes = utf8.GetBytes(responseHeader);
40 //向用戶端發送狀态資訊
41 client.Send(statusLineBytes);
42 //向用戶端發送回應頭
43 client.Send(responseBodyBytes);
44 //頭部和内容的分割行
45 client.Send(new byte[] {13, 10});
46 //向用戶端發送内容部分
47 client.Send(responseBodyBytes);
48 //斷開與用戶端的連結
49 client.Close();
50 if (Console.KeyAvailable)
51 {
52 break;
53 }
54 }
55 //關閉伺服器
56 socket.Close();
57 }
2.5 基于HttpListener的web伺服器
為了進一步簡化HTTP協定的監聽器,.NET在命名空間System.Net中提供了HttpListener類,伴随這個對象,.NET提供了一系列相關對象封裝了HTTP的處理工作,注意,這個類使用Http.sys系統元件來完成工作,是以,隻有在Windows XP SP2或者Server2003以上的作業系統中磁能使用。
1 private static void Main(string[] args)
2 {
3 //檢查系統是否支援
4 if (!HttpListener.IsSupported)
5 {
6 throw new System.InvalidOperationException("使用HTTPListener必須為Windows XP SP2或者Server 2003以上系統");
7 }
8 //注意字首必須以/正斜杠結尾
9 string[] prefixes = new string[] {"http://localhost:49125/"};
10 //建立監聽器
11 HttpListener listener = new HttpListener();
12 //增加監聽的字首
13 foreach (string s in prefixes)
14 {
15 listener.Prefixes.Add(s);
16 }
17 //開始監聽
18 listener.Start();
19 Console.WriteLine("監聽中。。。。。。");
20 while (true)
21 {
22 //注意:GetContext方法将阻塞線程,直到請求到達
23 HttpListenerContext context = listener.GetContext();
24 //取得請求對象
25 HttpListenerRequest request = context.Request;
26 Console.WriteLine("{0}{1} HTTP/1.1", request.HttpMethod, request.RawUrl);
27 Console.WriteLine("Accept:{0}", string.Join(",", request.AcceptTypes));
28 Console.WriteLine("Accept-Language:{0}", string.Join(",", request.UserLanguages));
29 Console.WriteLine("User-Agent:{0}", request.UserAgent);
30 Console.WriteLine("Accept-Encoding:{0}", request.Headers["Accept-Encoding"]);
31 Console.WriteLine("Connection:{0}", request.KeepAlive ? "Keep_Alive" : "close");
32 Console.WriteLine("Host:{0}", request.UserHostName);
33 Console.WriteLine("Pragma:{0}", request.Headers["Pragma"]);
34 //取得回應的對象
35 HttpListenerResponse response = context.Response;
36 //構造回應内容
37 string responseString =
38 @"<html><head><title>From Socket Server</title></head><body><h1>Hello,World</h1></body></html>";
39 //設定回應頭部内容,成都,編碼
40 response.ContentLength64 = Encoding.UTF8.GetByteCount(responseString);
41 response.ContentType = "text/html;chrset=UTF-8";
42 //輸出回應内容
43 Stream output = response.OutputStream;
44 StreamWriter writer = new StreamWriter(output);
45 writer.Write(responseString);
46 //必須關閉輸出流
47 writer.Close();
48 if (Console.KeyAvailable)
49 {
50 break;
51 }
52 }
53 //關閉伺服器
54 listener.Close();
55 Console.ReadLine();
56 }
上面三個關于簡單地模拟了一下Web伺服器的執行個體,實作結果如圖所示:
初心商城:初心商城
作者:韓迎龍(Kencery) MVC/.NET群:159227188
如果您認為這篇文章還不錯或者有所收獲,您可以通過右邊的“打賞”功能 打賞一杯咖啡,本頁版權歸作者和部落格園所有,歡迎轉載,但未經作者同意必須保留此段聲明,
且在文章頁面明顯位置給出原文連結,否則保留追究法律責任的權利