亚洲乱色熟女一区二区三区丝袜,天堂√中文最新版在线,亚洲精品乱码久久久久久蜜桃图片,香蕉久久久久久av成人,欧美丰满熟妇bbb久久久

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

C# 如何編寫一個web網(wǎng)頁服務(wù)器

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

前言


這里說的服務(wù)器是Web服務(wù)器,是類似IIS、Tomcat之類的,用來響應(yīng)瀏覽器請求的服務(wù)。


Socket模擬瀏覽器的Url Get請求


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


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


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

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

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

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


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

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


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



然后我們代碼實現(xiàn)如下:


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

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

//發(fā)送消息到服務(wù)端
void Send(Socket socketClient)
{
   //為了方便演示,僅用請求報文的前兩行即可。(切記:需要嚴(yán)格按照報文格式。如,最后需要連續(xù)兩次換行)
   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服務(wù)把域名解析成ip


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


3、獲取html文檔


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


注意:發(fā)送報文的時候需要嚴(yán)格按照報文格式。如,最后需要連續(xù)兩次換行、行末不能有空格等。


效果圖:



用Socket實現(xiàn)Web服務(wù)器


Web服務(wù)器的實現(xiàn)和我們上一篇的Socket聊天服務(wù)端其實也差不多。


不同之處就在于,解析請求報文,然后按HTTP協(xié)議回復(fù)標(biāo)準(zhǔn)的響應(yīng)報文(我這里為了簡單,就沒有按標(biāo)準(zhǔn)的協(xié)議來玩,僅僅只是實現(xiàn)了表面的效果)

代碼如下:


void ...()
{
   //1 創(chuàng)建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、開啟偵聽(等待客戶機發(fā)出的連接),并設(shè)置最大客戶端連接數(shù)為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 讀取客戶端發(fā)送過來的報文
private static void Receive(Socket newSocket)
{
   byte[] data = new byte[1024 * 1024];
   while (newSocket.Connected)
   {
       //讀取客戶端發(fā)送過來的數(shù)據(jù)
       int readLeng = newSocket.Receive(data, 0, data.Length, SocketFlags.None);
       //讀取客戶端發(fā)來的請求報文
       var requst = Encoding.UTF8.GetString(data, 0, readLeng);
    //解析請求報文的請求路徑(可以解析請求路徑、請求文件、文件類型)
    var requstFile = requst.Split("\r\n")[0].Split(" ")[1];
    //回復(fù)客戶端響應(yīng)報文
    Send(newSocket, requstFile);
   }
}

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


效果如下:




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


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


為什么不見三次握手


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


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



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


也就是說我們在用C#的Socket、TCP、HttpClient的時候根本就不用關(guān)注這些細(xì)節(jié)。


另外套接字有三種不同的類型:流套接字、數(shù)據(jù)報套接字和原始套接字。前兩者是標(biāo)準(zhǔn)套接字,分別對應(yīng)TCP和UDP。而原始套接字則更加底層更加牛逼,普通開發(fā)人員一般接觸不到。


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


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


結(jié)束


完整demo

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


轉(zhuǎn)自:農(nóng)碼一生

cnblogs.com/zhaopei/p/Socket2.html


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