C#实现Web服务器功能学习经验总结

开发 后端
这里介绍C#实现Web服务器功能的程序设计,从请求信息中获取请求类型。如果请求类型是GET,则从请求信息中获取所访问的HTML文件名。

学习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. }  

【编辑推荐】

  1. C#创建表单简单介绍
  2. C#修改DataReader默认行为
  3. C#设置CooperativeLevel概述
  4. C#表单增加控件简单描述
  5. C# EmployeePlug类概述
责任编辑:佚名 来源: 博客园
相关推荐

2009-08-13 18:13:27

C#学习经验

2009-08-11 14:20:41

C# .NET学习经验

2009-09-01 13:10:39

C#读取Word

2009-08-07 09:47:17

C#枚举C#数组

2009-09-01 13:00:05

C#实现Windows

2009-08-21 17:42:36

C#调用API

2009-08-24 14:56:01

C#连接Access

2009-09-02 14:14:44

C# COM接口转换

2009-08-27 11:21:36

C# override

2009-09-18 10:21:13

C#数组C#串操作

2009-09-16 17:13:54

学习Linq

2009-08-27 15:45:30

C#正则表达式

2013-12-18 15:54:21

2010-06-13 13:44:07

UML学习笔记

2011-07-21 13:40:17

java

2015-09-30 14:40:47

WebAPI接口设计

2011-07-08 13:15:52

JSP

2009-08-26 15:39:08

C#隐式类型局部变量

2009-08-24 17:34:14

C#创建XML Web

2010-06-02 09:06:26

SVN学习
点赞
收藏

51CTO技术栈公众号