狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

C# 如何編寫一個web網頁服務器

admin
2025年7月8日 12:39 本文熱度 174

前言


這里說的服務器是Web服務器,是類似IIS、Tomcat之類的,用來響應瀏覽器請求的服務。


Socket模擬瀏覽器的Url Get請求


首先瀏覽器的請求是HTTP協議。我們上一篇《你也可以寫個聊天程序 C# Socket學習》說過,HTTP是短連接,用完就斷開,是無狀態的。所以我們在等待響應的時候不需要另外開個線程循環等待。


也就是我們只需要通過Socket和服務器建立連接,然后發送請求,然后接收服務器的響應,這樣就完成了一次請求。


可是,我們一般訪問網頁的時候都是通過域名,沒有IP也沒有端口,怎么和服務器建立連接了。這里就需要用到我們上篇介紹的幾個類了:

//根據DNS獲取域名綁定的IP
foreach (var address in Dns.GetHostEntry("www.baidu.com").AddressList)
{
   Console.WriteLine($"百度IP:{address}");
}

//字符串轉IP地址
IPAddress ipAddress = IPAddress.Parse("192.168.1.101");

//通過IP和端口構造IPEndPoint對象,用于遠程連接
//通過IP可以確定一臺電腦,通過端口可以確定電腦上的一個程序
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 80);


對于HTTP沒有顯示端口默認都是80 (為了簡單這里就先不考慮HTTPS了)

知道了IP和端口,連接是可以建立了,為了得到正確的響應,我們應該給服務器發送什么消息呢?這里就需要用到HTTP協議了。


具體協議這里就不說了,我們先F12看看瀏覽器的請求報文,然后依葫蘆畫瓢試試,以http://fanyi-pro.baidu.com為例。(現在找個非HTTPS的地址也是不容易了)



然后我們代碼實現如下:


void ...()
{
   //得到主機信息
   IPHostEntry ipInfo = Dns.GetHostEntry(new Uri("http://fanyi-pro.baidu.com").Host);
   //取得IPAddress[]
   IPAddress[] ipAddr = ipInfo.AddressList;
   //得到服務器ip
   IPAddress ip = ipAddr[0];
   //組合遠程終結點
   IPEndPoint ipEndPoint = new IPEndPoint(ip, 80);
   //創建Socket 實例
   Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
   //嘗試連接
   socketClient.Connect(ipEndPoint);
   //發送請求
   Send(socketClient);
   //接收服務器的響應
   Receive(socketClient);
}

//接收來自服務端的消息
void Receive(Socket socketClient)
{
   byte[] data = new byte[1024 * 1024];
   while (true)
   {
       //讀取客戶端發送過來的數據
       int readLeng = socketClient.Receive(data, 0, data.Length, SocketFlags.None);
       textBox2.AppendText($"{socketClient.RemoteEndPoint}{Encoding.UTF8.GetString(data, 0, readLeng)}\r\n");
   }
}

//發送消息到服務端
void Send(Socket socketClient)
{
   //為了方便演示,僅用請求報文的前兩行即可。(切記:需要嚴格按照報文格式。如,最后需要連續兩次換行)
   var msg = $"GET / HTTP/1.1\r\nHost: {new Uri(textBox1.Text).Host}\r\n\r\n";
   socketClient.Send(Encoding.UTF8.GetBytes(msg));
}


整個流程也就是:


1、dns服務把域名解析成ip


2、通過ip和端口和服務器建立連接(三次握手)


3、獲取html文檔


4、根據文檔里面的鏈接(js、css、img)再重復以上過程


注意:發送報文的時候需要嚴格按照報文格式。如,最后需要連續兩次換行、行末不能有空格等。


效果圖:



用Socket實現Web服務器


Web服務器的實現和我們上一篇的Socket聊天服務端其實也差不多。


不同之處就在于,解析請求報文,然后按HTTP協議回復標準的響應報文(我這里為了簡單,就沒有按標準的協議來玩,僅僅只是實現了表面的效果)

代碼如下:


void ...()
{
   //1 創建Socket對象
   Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
   //2 綁定ip和端口
   IPAddress ip = IPAddress.Parse("127.0.0.1");
   IPEndPoint ipEndPoint = new IPEndPoint(ip, 80);
   socketServer.Bind(ipEndPoint);
   //3、開啟偵聽(等待客戶機發出的連接),并設置最大客戶端連接數為10
   socketServer.Listen(10);
   //阻塞等待客戶端連接
   Task.Run(() => { Accept(socketServer); });
}

//4 阻塞等待客戶端連接
private static void Accept(Socket socketServer)
{
   while (true)
   {
       //阻塞等待客戶端連接
       Socket newSocket = socketServer.Accept();
       Task.Run(() => { Receive(newSocket); });
   }
}

//5 讀取客戶端發送過來的報文
private static void Receive(Socket newSocket)
{
   byte[] data = new byte[1024 * 1024];
   while (newSocket.Connected)
   {
       //讀取客戶端發送過來的數據
       int readLeng = newSocket.Receive(data, 0, data.Length, SocketFlags.None);
       //讀取客戶端發來的請求報文
       var requst = Encoding.UTF8.GetString(data, 0, readLeng);
    //解析請求報文的請求路徑(可以解析請求路徑、請求文件、文件類型)
    var requstFile = requst.Split("\r\n")[0].Split(" ")[1];
    //回復客戶端響應報文
    Send(newSocket, requstFile);
   }
}

//6 回復客戶端響應報文
private static void Send(Socket newSocket, string requstFile)
{
   //這里如果請求的根目錄,默認顯示Index.html
   if (requstFile == "/" ) requstFile = "/Index.html";
   var msg = File.ReadAllText(Directory.GetCurrentDirectory() + requstFile);
   //把消息內容轉成字節數組后發送
   newSocket.Send(Encoding.UTF8.GetBytes(msg));
   //回復響應后馬上關閉連接
   newSocket.Shutdown(SocketShutdown.Both);
   newSocket.Close();
}


效果如下:




由此我們知道了.NET Core為什么可以在不需要iis的情況下,一個黑窗體就提供了對網址的訪問。其實也就是KestrelServer通過Socket綁定并監聽端口提供的服務。


注意:我們綁定的ip是127.0.0.1socketServer.Bind(ipEndPoint),所以我們測試的時候只能在瀏覽器輸入127.0.0.1或者localhost。如果想通過內外ip訪問,我們可以綁定任意ipIPAddress.Any。如socketServer.Bind(new IPEndPoint(IPAddress.Any, port))。


為什么不見三次握手


對于HTTP/TCP可能大家多少都聽過三次握手,可是在我們在用Socket編寫Web服務器的時候并沒有看到相關的東西啊,這是怎么回事。


因為我們在客戶端執行連接socketClient.Connect(ipEndPoint)的時候已經進行了三次握手



具體可細讀小坦克大佬(https://www.cnblogs.com/TankXiao/archive/2012/10/10/2711777.html)的文章。


也就是說我們在用C#的Socket、TCP、HttpClient的時候根本就不用關注這些細節。


另外套接字有三種不同的類型:流套接字、數據報套接字和原始套接字。前兩者是標準套接字,分別對應TCP和UDP。而原始套接字則更加底層更加牛逼,普通開發人員一般接觸不到。


我們說的HTTP、TCP、UDP之類都是網絡協議,那協議到底是什么?通俗的說其實只是你我他之間的一個約定而已,大家都按規定了來那就可以說是協議。


而HTTP又是建立在TCP之上的,也就是說基礎協議之后再加約定又可以成為一種新的協議。下章我們將用Socket來實現ModbusTCP協議對寄存器讀和寫。


結束


完整demo

https://github.com/zhaopeiym/BlogDemoCode/tree/master/Socket編程/2HTTP?


轉自:農碼一生

cnblogs.com/zhaopei/p/Socket2.html


該文章在 2025/7/9 9:13:52 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved