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服务器功能的代码如下:

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

【编辑推荐】

  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#正则表达式

2015-09-30 14:40:47

WebAPI接口设计

2011-07-21 13:40:17

java

2010-06-13 13:44:07

UML学习笔记

2013-12-18 15:54:21

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技术栈公众号