亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

TCP/IP協議學習(四)基于C#Socket的Web服務器---靜態資源處理

2019-11-14 13:32:07
字體:
來源:轉載
供稿:網友

目錄

1. C# Socket通訊

2. HTTP 解析引擎

3. 資源讀取和返回

4. 服務器測試和代碼下載

  Web服務器是Web資源的宿主,它需要處理用戶端瀏覽器的請求,并指定對應的Web資源返回給用戶,這些資源不僅包括HTML文件,JS腳本,JPG圖片等,還包括由軟件生成的動態內容。為了滿足上述需求,一個完整的Web服務器工作流程:

  1) 服務器獲得瀏覽器通過TCP/ip連接向服務器發送的http請求數據包。

  2) HTTP請求經過Web服務器的HTTP解析引擎分析得出請求方法、資源地址等信息,然后開始處理。

  3) 對于靜態請求,則在服務器上查詢請求url路徑下文件,并返回(如果未找到則返回404 No Found)。

  4) 涉及動態請求,如CGI, Ajax, asp等,則根據http方法,采取不同處理。

  

  Web服務器的核心由C#%20Socket通訊,http解析引擎,靜態資源文件查找,動態數據接收和發送4部分組成,本節因為個人編寫進度原因主要實現前3個部分(即能夠查詢靜態資源的Web服務器),動態數據處理因為涉及的處理方式CGI,AJAX,ASP的方法不同,后續完成后在總結相關知識。

1.%20C#%20Socket通訊 

  C#%20Socket通過對TCP/IP協議進行封裝,用于實現滿足TCP通訊的API。在B/S架構中,服務器端的處理和C/S連接基本相同,主要工作包含:創建Socket套接字,監聽連接,建立連接,獲得請求,處理并返回數據,關閉連接等。

  程序入口函數,采用輪詢方式實現對客戶端請求的監聽。

%20%20%20%20%20%20%20%20%20%20//創建監聽線程%20%20%20%20%20%20%20%20%20%20Thread%20Listen_thread%20=%20new%20Thread(socket_listen);%20%20%20%20%20%20%20%20%20%20Listen_thread.IsBackground%20=%20false;%20%20%20%20%20%20%20%20%20%20Listen_thread.Start();%20%20%20%20%20%20%20%20

  監聽線程,創建Socket套接字,綁定并監聽指定端口,等待連接建立,連接建立后,考慮到網頁請求高并發的特性,采用另開線程的方式來處理建立的連接,從而實現并發服務器模式。

%20%20%20%20%20%20%20%20%20%20%20%20Socket%20server_socket%20=%20null;%20%20%20%20%20%20%20%20%20%20%20%20//監聽的IP地址和端口%20作為服務器,綁定的只能是本機Ip地址或者環回地址(不能與系統其它進程端口沖突)%20%20%20%20%20%20%20%20%20%20%20%20//如果綁定為本節IP地址,局域網下其它設備可以通過http://host:port來訪問當前服務器%20%20%20%20%20%20%20%20%20%20%20%20string%20host%20=%20"127.0.0.1";%20%20%20%20%20%20%20%20%20%20%20%20int%20port%20=%203000;%20%20%20%20%20%20%20%20%20%20%20%20IPAddress%20ip%20=%20IPAddress.Parse(host);%20%20%20%20%20%20%20%20%20%20%20%20IPEndPoint%20ipe%20=%20new%20IPEndPoint(ip,%20port);%20%20%20%20%20%20%20%20%20%20%20%20//新建Socket套接字,綁定在指定的端口并開始監聽%20%20%20%20%20%20%20%20%20%20%20%20server_socket%20=%20new%20Socket(AddressFamily.InterNetwork,%20SocketType.Stream,%20

  雖然HTTP請求包的內容很多,但因為目前實現的功能較少,所以關注的只有http報文起始行就可以,而首部字段可以直接丟棄不處理,后續如果使用認證機制,如白名單,黑名單過濾,帳號/密碼保護,資源權限管理等,首部仍然要處理。

  對于http報文起始行, 內部以space隔開,并以'/r/n'作為結尾與首部隔開。其中GET:HTTP方法, '/' :資源路徑url, HTTP/1.1:協議版本,參照http權威指南的內容,  HTTP協議的常見方法有GET, PUT, DELETE, POST, HEAD這5種,本節中的靜態服務器主要涉及到GET方法。了解了需要如何解析HTTP請求報文后,我們先定義一個HTTP報文解析結構,用于存儲到解析的信息。

        public class HTTPPrase        {           //http方法           public string http_method;           //http資源           public string url;           //http版本號           public string version;           //url解析的請求網頁類型           public string type;        };

  下面我們就要開始利用C#提供的String方法來截取http報文來實現上述結構體內參數的初始化。

            int pos;           //根據/r/n截斷,獲取http報文首部并轉換為小寫,方便后續處理           //Get / HTTP/1.1/r/n           pos = str.IndexOf("/r/n");           string str_head = str.Substring(0, pos);           str_head = str_head.ToLower();            //根據' '來截斷起始行,并賦值給對應參數           string[] arr = Regex.Split(str_head, @"/s+");           HTTPServer.HTTPPrase http_head = new HTTPServer.HTTPPrase();           http_head.http_method = arr[0];      // "Get"           http_head.url = arr[1];              // "/"           http_head.version = arr[2];          // "HTTP/1.1"            //判斷是否有通過ajax要求獲得或者提交的動態數據            http_head.ajax_status = str_head.IndexOf(".ajax") != -1 ? true : false;           byte[] bs = http_head.ajax_status == true ? ajax_process(http_head, str) : static_process(http_head, str);           return bs;

  下面就可以把數據提交給后端接口,進行處理。因為動態網頁處理需要網頁端和后端相互的配合,工作量較大,因此本節主要闡述靜態網頁請求的實現。

3. 資源讀取和返回

  局域網Web請求一般是通過ip+port的模式直接訪問服務器端,所以第一個接收到的請求的url為‘/',這時我們需要將它映射到服務端定位的訪問主頁,目前設置為index.html,對于其它請求,url的值一般是'/xxx/xxx.js", '/xxx/xxx.jpg"等,而在服務器中讀取時我們需要定義絕對地址,所以還要在前面添加資源存儲的根地址,目前將程序當前所在文件夾+html作為資源的根地址,而且操作系統存儲的數據路徑為/xxx/xxx.js,所以對于請求中url數據還要替換為'//'(為了保證轉義符能夠轉變為路徑符,需要用'//'表示實際的'/'),此外為了后續的http響應報文中返回正確的Content-Type字段,還有截取'.'后字段,來獲取請求文件的類型。

              //獲得當前程序所在的文件夾              string url_str = System.AppDomain.CurrentDomain.SetupInformation.applicationBase;              if (string.Compare(head.url, "/") == 0)              {                 //對于首個請求127.0.0.1:3000/ 返回index.html                 url_str += "html//index.html";                 head.type = "html";              }              else              {                 //其它請求 如/spring.js 替換為 .../html/spring.js便于C#查詢文件路徑                 url_str =url_str + "html//" + head.url.Substring(1);                 url_str = url_str.Replace('/', '//');                 int pos = url_str.IndexOf('.');                //獲得當前請求的網頁類型                 head.type = url_str.Substring(pos + 1);              }

   到此為止,完成了整個http解析的過程,包括http方法, url資源地址獲得并轉換為windows系統路徑,協議版本獲得三個部分。對于靜態網頁請求,后續就比較簡單,查詢系統路徑下資源,通過文件流打開,并以字符流的形式放置在內存中,作為http響應報文的正文部分。

             //以文件流的方式打開指定路徑內文件             using (FileStream fs = new FileStream(url_str, FileMode.Open, Fileaccess.Read))             {                  //StreamReader temp = new StreamReader(fs, Encoding.Default);                  int fslen = (int)fs.Length;                  byte[] fbyte = new byte[fslen];                  int r = fs.Read(fbyte, 0, fslen);                  fs.Close();                                 //......            }    

    文件打開成功后,我們就要生成http響應報文了,http響應報文和請求報文相同,也由三部分構成。

  狀態碼:主要為客戶端提供一種理解事務處理結果的便捷方式。主要實現的有:

  HTTP/1.1 200 OK 請求沒有問題,實體的主體部分包含請求的資源

      HTTP/1.1 400 Bad Request 通知客戶端它發送了一個錯誤的請求

  HTTP/1.1 401 Unauthorized 與適當的首部一同返回,通知客戶端進行相應的認證

      HTTP/1.1 404 No Found 說明服務器無法找到請求的URL

 響應首部:為客戶端提供額外的關于服務器的消息,本項目中實現比較簡單:

  Content-type:CurrentType/r/n

  Server:C# Web/r/n

  Content-Length:CurrentLength/r/n

  Connection: close

   其中Contenet-type需要根據我們上文獲得的type類型來替換,這里闡述常見的替換規則。

  

    Content-Length字段是http響應報文正文的長度,即我們獲得資源的總長度(上文中fslen), 最后將狀態碼,響應首部和正文數據整合在一起通過socket發送到客戶端,就實現了靜態服務器的全部過程。

                            string HTTP_Current_Head = HTTPServer.HTTP_OK_Head.Replace("CurrentLength", Convert.ToString(fslen));                            //根據不同url需要返回不同的首部類型 具體對比詳見http://tool.oschina.net/commons                           switch (head.type)                            {                                case "jpg":                                    HTTP_Current_Head = HTTP_Current_Head.Replace("CurrentType", "application/x-jpg");                                    break;                                case "png":                                    HTTP_Current_Head = HTTP_Current_Head.Replace("CurrentType", "image/png");                                    break;                                case "html":                                    HTTP_Current_Head = HTTP_Current_Head.Replace("CurrentType", "text/html");                                    break;                                case "gif":                                    HTTP_Current_Head = HTTP_Current_Head.Replace("CurrentType", "image/gif");                                    break;                                case "js":                                    HTTP_Current_Head = HTTP_Current_Head.Replace("CurrentType", "application/x-javascript");                                    break;                                case "asp":                                    HTTP_Current_Head = HTTP_Current_Head.Replace("CurrentType", "text/asp");                                    break;                                default:                                    HTTP_Current_Head = HTTP_Current_Head.Replace("CurrentType", "text/html");                                    break;                            }                                                        send_str = HTTPServer.HTTP_OK_Start + HTTP_Current_Head;                            byte[] head_byte = new byte[send_str.Length];                            head_byte = Encoding.UTF8.GetBytes(send_str);                            //字符串流合并,生成發送文件                             //之前采用的是byte[]->string, string合并, string->byte[],這種方法讀取圖片亂碼                            //因此修改為,string合并, string->byte[], byte[]合并方式,讀取圖片成功                            byte[] send_byte = new byte[send_str.Length + fbyte.Length];                            Buffer.BlockCopy(head_byte, 0, send_byte, 0, head_byte.Length);                            Buffer.BlockCopy(fbyte, 0, send_byte, head_byte.Length * sizeof(byte), fbyte.Length);                            Console.WriteLine("File Send....");                            return send_byte;

4. 服務器測試和代碼下載

  到現在為止,一個簡單的靜態web服務器就實現了,將希望訪問的資源文件放入當前程序文件夾/html/下, 并將首頁定義為index.html, 點開服務器程序,瀏覽器中輸入http://127.0.0.1:3000, 就可以查看返回的網頁。

具體程序參考:Web服務器下載

 

 


上一篇:使用VisualStudio2015Community開發windows服務

下一篇:VS2013生成事件,刪除不必要的DLL

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品欧美亚洲777777| 亚洲美女精品成人在线视频| 久久久久99精品久久久久| 亚洲男人7777| 亚洲高清不卡av| 久久人人97超碰精品888| 国产美女高潮久久白浆| 亚洲区一区二区| 日韩精品电影网| 日韩电视剧在线观看免费网站| 激情懂色av一区av二区av| 久久精品电影网站| 欧美性猛交xxxx黑人| 日韩成人在线播放| 欧美主播福利视频| 日韩av影视在线| 久久久女人电视剧免费播放下载| 国产精品国内视频| 亚洲国产精品va在线| 精品国产精品自拍| 97视频在线观看视频免费视频| 亚洲最大成人免费视频| 亚洲电影免费观看高清| 亚洲成人久久久| 国产精品视频一区二区高潮| 国产精品日韩专区| 亚洲精品视频免费| 欧美一级淫片videoshd| 欧美视频一区二区三区…| 国产一区二区欧美日韩| 亚洲国产精品悠悠久久琪琪| 日韩毛片在线看| 欧美老女人www| 成人性生交大片免费看小说| 亚洲韩国青草视频| 欧美麻豆久久久久久中文| 在线日韩欧美视频| 欧美日韩美女在线| 国产午夜精品视频| 中文字幕亚洲自拍| 国产一区二区三区在线视频| 欧美精品第一页在线播放| 国产精品国产亚洲伊人久久| 欧美大片免费观看| 欧美怡红院视频一区二区三区| 日韩精品有码在线观看| 欧美激情二区三区| 欧美精品激情blacked18| 欧美韩日一区二区| 91麻豆桃色免费看| 国产精品高潮粉嫩av| 国产精品视频公开费视频| 亚洲国产一区自拍| 亚洲一区av在线播放| 国产精品爽爽爽爽爽爽在线观看| 青草青草久热精品视频在线观看| 亚洲影院高清在线| 亚洲精品在线视频| 亚洲第一网站男人都懂| 成人国产精品久久久久久亚洲| 成人午夜黄色影院| 亚洲视屏在线播放| 欧美与黑人午夜性猛交久久久| 日韩专区在线播放| 日韩欧美国产成人| 日韩在线观看电影| 精品色蜜蜜精品视频在线观看| 国产成人精品av在线| 亚洲综合精品一区二区| 亚洲成人中文字幕| 日韩欧美综合在线视频| 亚洲欧美一区二区三区在线| 欧美激情女人20p| 日韩av在线网| 国产91色在线|| 91av视频在线观看| 搡老女人一区二区三区视频tv| 亚洲xxx自由成熟| 久久伊人精品一区二区三区| 久久久久久久久久婷婷| 亚洲欧美国产精品专区久久| 日韩成人av在线播放| 国产精品三级美女白浆呻吟| 欧美又大又硬又粗bbbbb| 亚洲风情亚aⅴ在线发布| 亚洲精品久久久久久久久久久| 亚洲精品黄网在线观看| 亚洲人成伊人成综合网久久久| 亚洲аv电影天堂网| 欧美刺激性大交免费视频| 欧美日韩国产限制| 91国语精品自产拍在线观看性色| 色婷婷成人综合| 日本不卡免费高清视频| 欧美在线视频免费| 色多多国产成人永久免费网站| 久久久久久尹人网香蕉| 一本色道久久综合狠狠躁篇的优点| 国产999精品| 国产精品∨欧美精品v日韩精品| 国产精品中文字幕久久久| 亚洲理论在线a中文字幕| 色www亚洲国产张柏芝| 亚洲精品一区在线观看香蕉| 国产在线高清精品| 国产美女被下药99| 91精品国产自产在线| 久久久综合免费视频| 久久香蕉频线观| 中文字幕免费国产精品| 欧美一乱一性一交一视频| 在线日韩av观看| 久久69精品久久久久久久电影好| 色一情一乱一区二区| 欧美电影《睫毛膏》| 久久露脸国产精品| 国产亚洲精品美女| 亚洲精品小视频在线观看| 中文字幕久久久| 精品国产区一区二区三区在线观看| 全亚洲最色的网站在线观看| 欧美激情一区二区三区在线视频观看| 欧美大片大片在线播放| 亚洲色图欧美制服丝袜另类第一页| 中文精品99久久国产香蕉| 亚洲欧美日韩成人| 92国产精品久久久久首页| 日韩精品亚洲视频| 亚洲欧美日韩区| 久久av中文字幕| 秋霞午夜一区二区| 亚洲成人av中文字幕| 成人www视频在线观看| 久久人人爽人人爽爽久久| 色多多国产成人永久免费网站| 插插插亚洲综合网| 久久久久日韩精品久久久男男| 操人视频在线观看欧美| 91色中文字幕| 欧美高清激情视频| 成人av在线天堂| 国产精品日韩在线观看| 久久精品夜夜夜夜夜久久| 亚洲一区中文字幕在线观看| 亚洲成人久久电影| 日韩视频永久免费观看| 亚洲电影天堂av| 欧美色视频日本版| 91美女片黄在线观看游戏| 欧美激情一级二级| 国产xxx69麻豆国语对白| 91国产视频在线播放| 欧美日韩xxxxx| 美日韩精品视频免费看| 免费97视频在线精品国自产拍| 国产网站欧美日韩免费精品在线观看| 久久中文字幕在线视频| 伊人久久男人天堂| 日韩欧美综合在线视频| 久久综合亚洲社区| 国产亚洲精品一区二555| 国产精品扒开腿做爽爽爽的视频| 黑人巨大精品欧美一区二区三区| 96sao精品视频在线观看|