c#實現Web服務器

學習C#時,經常會遇到Web服務器功能的程序設計問題,這裏將介紹C#實現Web服務器功能的程序設計問題的解決方法。

C#實現Web服務器功能的程序設計

根據HTTP協議的作用原理,實現GET請求的Web服務器程序的方法如下:

創建TcpListener類對象,監聽某端口(任意輸入閒置端口 如:8080 )。等待、接受客戶機連接到該端口,得到與客戶機連接的socket;從與socket關聯的輸入流中讀取一行客戶機提交的請求信息,請求信息的格式爲:GET 路徑/文件名 HTTP/1.0。從請求信息中獲取請求類型。如果請求類型是GET,則從請求信息中獲取所訪問的HTML文件名。沒有HTML文件名時,則以index.html作爲文件名;

如果HTML文件存在,則打開HTML文件,把HTTP頭信息和HTML文件內容通過socket傳回給Web瀏覽器,然後關閉文件。否則發送錯誤信息給Web瀏覽器;關閉與相應Web瀏覽器連接的socket字。

C#實現Web服務器功能的代碼如下:

  1. using System;  
  2. using System.IO;  
  3. using System.Net;  
  4. using System.Net.Sockets;  
  5. using System.Text;  
  6. using System.Threading ;  
  7.  
  8. class MyWebServer  
  9. {  
  10.  
  11. private TcpListener myListener ;  
  12. private int port = 8080 ; // 選者任何閒置端口  
  13.  
  14. //開始兼聽端口  
  15. //同時啓動一個兼聽進程  
  16. public MyWebServer()  
  17. {  
  18. try  
  19. {  
  20. //開始兼聽端口  
  21. myListener = new TcpListener(port) ;  
  22. myListener.Start();  
  23. Console.WriteLine("Web Server Running... Press ^C to Stop...");  
  24. //同時啓動一個兼聽進程 ''StartListen''  
  25. Thread th = new Thread(new ThreadStart(StartListen));  
  26. th.Start() ;  
  27.  
  28. }  
  29. catch(Exception e)  
  30. {  
  31. Console.WriteLine("兼聽端口時發生錯誤 :" +e.ToString());  
  32. }  
  33. }  
  34. public void SendHeader(string sHttpVersion, string sMIMEHeader, 
    int iTotBytes, string sStatusCode, ref Socket mySocket)  
  35. {  
  36.  
  37. String sBuffer = "";  
  38.  
  39. if (sMIMEHeader.Length == 0 )  
  40. {  
  41. sMIMEHeader = "text/html"; // 默認 text/html  
  42. }  
  43.  
  44. sBuffersBuffer = sBuffer + sHttpVersion + sStatusCode + "\r\n";  
  45. sBuffersBuffer = sBuffer + "Server: cx1193719-b\r\n";  
  46. sBuffersBuffer = sBuffer + "Content-Type: " + sMIMEHeader + "\r\n";  
  47. sBuffersBuffer = sBuffer + "Accept-Ranges: bytes\r\n";  
  48. sBuffersBuffer = sBuffer + "Content-Length: " + iTotBytes + "\r\n\r\n";  
  49.  
  50. Byte[] bSendData = Encoding.ASCII.GetBytes(sBuffer);  
  51.  
  52. SendToBrowser( bSendData, ref mySocket);  
  53.  
  54. Console.WriteLine("Total Bytes : " + iTotBytes.ToString());  
  55.  
  56. }  
  57.  
  58. public void SendToBrowser(String sData, ref Socket mySocket)  
  59. {  
  60. SendToBrowser (Encoding.ASCII.GetBytes(sData), ref mySocket);  
  61. }  
  62.  
  63. public void SendToBrowser(Byte[] bSendData, ref Socket mySocket)  
  64. {  
  65. int numBytes = 0;  
  66.  
  67. try  
  68. {  
  69. if (mySocket.Connected)  
  70. {  
  71. if (( numBytes = mySocket.Send(bSendData, bSendData.Length,0)) == -1)  
  72. Console.WriteLine("Socket Error cannot Send Packet");  
  73. else  
  74. {  
  75. Console.WriteLine("No. of bytes send {0}" , numBytes);  
  76. }  
  77. }  
  78. else  
  79. Console.WriteLine("連接失敗....");  
  80. }  
  81. catch (Exception e)  
  82. {  
  83. Console.WriteLine("發生錯誤 : {0} ", e );  
  84.  
  85. }  
  86. }  
  87. public static void Main()  
  88. {  
  89. MyWebServer MWS = new MyWebServer();  
  90. }  
  91. public void StartListen()  
  92. {  
  93.  
  94. int iStartPos = 0;  
  95. String sRequest;  
  96. String sDirName;  
  97. String sRequestedFile;  
  98. String sErrorMessage;  
  99. String sLocalDir;  
  100.  
  101. String sMyWebServerRoot = "E:\\MyWebServerRoot\\"; //設置你的虛擬目錄  
  102.  
  103. String sPhysicalFilePath = "";  
  104. String sFormattedMessage = "";  
  105. String sResponse = "";  
  106.  
  107. while(true)  
  108. {  
  109. //接受新連接  
  110. Socket mySocket = myListener.AcceptSocket() ;  
  111.  
  112. Console.WriteLine ("Socket Type " +mySocket.SocketType );  
  113. if(mySocket.Connected)  
  114. {  
  115. Console.WriteLine("\nClient Connected!!\n=\nCLient IP {0}\n",mySocket.RemoteEndPoint) ;  
  116.  
  117. Byte[] bReceive = new Byte[1024] ;  
  118. int i = mySocket.Receive(bReceive,bReceive.Length,0) ;  
  119.  
  120. //轉換成字符串類型  
  121. string sBuffer = Encoding.ASCII.GetString(bReceive);  
  122.  
  123.  
  124. //只處理"get"請求類型  
  125. if (sBuffer.Substring(0,3) != "GET" )  
  126. {  
  127. Console.WriteLine("只處理get請求類型..");  
  128. mySocket.Close();  
  129. return;  
  130. }  
  131.  
  132. // 查找 "HTTP" 的位置  
  133. iStartPos = sBuffer.IndexOf("HTTP",1);  
  134.  
  135. string sHttpVersion = sBuffer.Substring(iStartPos,8);  
  136.  
  137. // 得到請求類型和文件目錄文件名  
  138. sRequest = sBuffer.Substring(0,iStartPos - 1);  
  139.  
  140. sRequest.Replace("\\","/");  
  141.  
  142. //如果結尾不是文件名也不是以"/"結尾則加"/"  
  143. if ((sRequest.IndexOf(".") <1) && (!sRequest.EndsWith("/")))  
  144. {  
  145. sRequestsRequest = sRequest + "/";  
  146. }  
  147.  
  148. //得帶請求文件名  
  149. iStartPos = sRequest.LastIndexOf("/") + 1;  
  150. sRequestsRequestedFile = sRequest.Substring(iStartPos);  
  151.  
  152. //得到請求文件目錄  
  153. sDirName = sRequest.Substring(sRequest.IndexOf("/"), sRequest.LastIndexOf("/")-3);  
  154.  
  155. //獲取虛擬目錄物理路徑  
  156. sLocalDir = sMyWebServerRoot;  
  157.  
  158. Console.WriteLine("請求文件目錄 : " + sLocalDir);  
  159.  
  160. if (sLocalDir.Length == 0 )  
  161. {  
  162. sErrorMessage = "<H2>Error!! Requested Directory does not exists</H2><Br>";  
  163. SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket);  
  164. SendToBrowser(sErrorMessage, ref mySocket);  
  165. mySocket.Close();  
  166. continue;  
  167. }  
  168.  
  169. if (sRequestedFile.Length == 0 )  
  170. {  
  171. // 取得請求文件名  
  172. sRequestedFile = "index.html";  
  173. }  
  174.  
  175.  
  176. String sMimeType = "text/html";  
  177.  
  178. sPhysicalFilePath = sLocalDir + sRequestedFile;  
  179. Console.WriteLine("請求文件: " + sPhysicalFilePath);  
  180.  
  181. if (File.Exists(sPhysicalFilePath) == false)  
  182. {  
  183.  
  184. sErrorMessage = "<H2>404 Error! File Does Not Exists...</H2>";  
  185. SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket);  
  186. SendToBrowser( sErrorMessage, ref mySocket);  
  187.  
  188. Console.WriteLine(sFormattedMessage);  
  189. }  
  190.  
  191. else  
  192. {  
  193. int iTotBytes=0;  
  194.  
  195. sResponse ="";  
  196.  
  197. FileStream fs = new FileStream(sPhysicalFilePath, 
    FileMode.Open, FileAccess.Read, FileShare.Read);  
  198.  
  199. BinaryReader reader = new BinaryReader(fs);  
  200. byte[] bytes = new byte[fs.Length];  
  201. int read;  
  202. while((read = reader.Read(bytes, 0, bytes.Length)) != 0)  
  203. {  
  204. sResponsesResponse = sResponse + Encoding.ASCII.GetString(bytes,0,read);  
  205.  
  206. iTotBytesiTotBytes = iTotBytes + read;  
  207.  
  208. }  
  209. reader.Close();  
  210. fs.Close();  
  211.  
  212. SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);  
  213. SendToBrowser(bytes, ref mySocket);  
  214. //mySocket.Send(bytes, bytes.Length,0);  
  215. }  
  216. mySocket.Close();  
  217. }  
  218. }  
  219. }  
  220. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章