博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用Socket来简单实现IIS服务器
阅读量:5037 次
发布时间:2019-06-12

本文共 9049 字,大约阅读时间需要 30 分钟。

    刚刚接触ASP.NET编程,为了更好的屡清楚服务器的处理过程,就用Socket模拟服务器来处理请求。用Socket来模拟服务器的时候,同样是自己来封装一些对应的类文件。包括 HttpRequest、HttpResponse、HttpContext、HttpApplication、IHttpHandel。主要的执行流程是:先用Socket来创建一个简单的服务器,进行监听,当监听到请求后将请求交给处理程序去处理,应用程序中根据请求的是静态资源还是动态资源做出不同的处理。然后通过Socket对象将响应类容给发送回去。这只是为了更好的了解服务器的处理,进行了一个简单的模拟,程序中有很多的bug,但是能够实现基本的功能

HttpRequest类

主要包含几个主要的属性:请求方式,请求地址,请求协议的版本号

1     public class HttpRequest 2     { 3         public HttpRequest (string str) 4         { 5             if (string.IsNullOrEmpty(str)) 6             { 7                 return; 8             } 9             string head = str.Replace("\r\n", "$").Split('$')[0];10             string[] heads = head.Split(' ');11             Method = heads.Length>1? heads[0]:"";12             //得到请求的绝对路径13             Url = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), heads.Length>1? heads[1].Substring(1):heads[0]);14             Protocol = heads.Length > 1 ? heads[2] : "";15 16         }17 18         public string Method { get; set; }19         public string Url { get; set; }20         public string Protocol { get; set; }21     }
HttpRequest类

HttpResponse类

包含响应头和响应体,在网络上传输的是二进制文件,故将这两个属性定义为byte[],中间还包含其他的一些属性。其中响应长度是动态的,在处理程序里面设置

1     public class HttpResponse 2     { 3         public HttpResponse (HttpRequest request) 4         { 5             this.request = request; 6             Type = GetType(Path.GetExtension(request.Url)); 7         } 8  9         private HttpRequest request;10         private string Type { get; set; }11         public int Length { get; set; }12         public byte[] Head {13             get14             {15 16                 //                -----响应报文------------17                 //HTTP/1.1 200 OK18                 //Connection: keep-alive19                 //Date: Thu, 26 Jul 2007 14:00:02 GMT20                 //Server: Microsoft-IIS/6.021                 //X-Powered-By: ASP.NET22                 //Content-Length: 19023                 //Content-Type: text/html24                 //Set-Cookie: ASPSESSIONIDSAATTCSQ=JOPPKDCAMHHBEOICJPGPBJOB; path=/25                 //Cache-control: private 26                 ////--空行--27                 //响应体(正文)28 29                 StringBuilder sb = new StringBuilder();30                 sb.AppendFormat("{0} {1}\r\n", request.Protocol, "200 OK");31                 sb.AppendLine("Date:" + DateTime.Now.ToString());32                 sb.AppendLine("Server:QIGANG-PC");33                 sb.AppendLine("Content-Length:" + Length);34                 sb.AppendLine("Content-Type:" + Type);35                 sb.AppendLine();36                 return Encoding.UTF8.GetBytes(sb.ToString());37 38 39             }40         }41         public byte[] Body { get; set; }42 43     ///根据请求来得到响应的类型44         private string GetType (string ext)45         {46             string type1 = "text/html;charset=utf-8";47             switch (ext)//mime-type48             {49                 case ".aspx":50                 case ".html":51                 case ".htm":52                     type1 = "text/html;charset=utf-8";53                     break;54                 case ".png":55                     type1 = "image/png";56                     break;57                 case ".gif":58                     type1 = "image/gif";59                     break;60                 case ".jpg":61                 case ".jpeg":62                     type1 = "image/jpeg";63                     break;64                 case ".css":65                     type1 = "text/css";66                     break;67                 case ".js":68                     type1 = "application/x-javascript";69                     break;70                 default:71                     type1 = "text/plain;charset=gbk";72                     break;73             }74             return type1;75         }76     }
HttpResponse类

HttpContext类

在这个类里面简单的封装了两个成员对象,就是HttpRequest和HttpResponse两个成员,其它的就从简了

1     public class HttpContext 2     { 3         public HttpContext (string str) 4         { 5             Request = new HttpRequest(str); 6             Response = new HttpResponse(Request); 7         } 8         public HttpRequest Request { get; set; } 9         public HttpResponse Response { get; set; }10     }
HttpContext类

IHttpHandel接口

由于在客户端请求的数据中可能请求的是一个动态网页,这是就需要交给.NET Framework 来进行处理,为了方便处理,故要求所有的动态网页都需要实现一个接口,只有实现了这个接口的程序才能够被浏览器给请求到

1     public interface IHttpHandel2     {3         void ProcessRequest (HttpContext context);4     }
IHttpHandel接口

服务器端Socket程序

在这主要是启动一个Socket对象,来进行连接的监听,然后把监听到的对象交给处理程序 HttpApplication进行处理

1         private void button1_Click (object sender, EventArgs e) 2         { 3             socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 4             socket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 22822)); 5             socket.Listen(10); 6             Thread thread = new Thread((obj) => 7             { 8                 Socket server = obj as Socket; 9                 while (true)10                 {11                     Socket client = server.Accept();12                     Thread cth = new Thread((obj2) =>13                     {14                         Socket cSocket = obj2 as Socket;15 16                         byte[] by = new byte[cSocket.Available];17                         cSocket.Receive(by, 0, by.Length, SocketFlags.None);18             //拿到请求头文件19                         string str = Encoding.UTF8.GetString(by);20 21                         /*--------- 调用请求处理函数进行处理 ---------*/22                         HttpContext context = new HttpContext(str);23                         HttpApplication app = new HttpApplication(context, cSocket);24                     });25                     cth.IsBackground = true;26                     cth.Start(client);27                 }28             });29             thread.IsBackground = true;30             thread.Start(socket);31         }
Socket服务端程序

HttpApplication类

这个类需要传递一个参数,上下文对象。然后进行请求的解析,根据请求的是静态资源还是动态资源去进行不同的处理。如果是静态资源就直接冲磁盘文件中读取返回,如果是动态资源,就交给对应的类。当然前提是请求的资源名称就对应了一个类文件。

1     public class HttpApplication 2     { 3     //构造函数 4         public HttpApplication (HttpContext context,Socket socket) 5         { 6             string url =context.Request.Url; 7             if(string.IsNullOrEmpty(url)){ 8                 return; 9             }10             string ext = Path.GetExtension(url);11         //请求的是动态资源文件12             if (ext == ".aspx")13             {14         //下面的代码中也就没有进行错误的处理了,主要是模拟,没有考虑其他的情况15         //拿到请求资源的文件名(不包含后缀)16                 string cs = Path.GetFileNameWithoutExtension(url);17         //得到当前程序的程序集18                 Assembly ass = Assembly.GetExecutingAssembly();19         //拿到请求的文件对应的类20                 Type type = ass.GetType(ass.GetName().Name + "." + cs, true, true);21         //创建对象,进行调用22                 IHttpHandel handel = Activator.CreateInstance(type) as IHttpHandel;23                 handel.ProcessRequest(context);24         //上面几句话可以合并到一起,拿到程序集后直接CreateInstance();25             }26             else if (ext == ".ashx")27             {28             }29             else//访问静态资源30             {31                //直接从磁盘中读取请求的资源文件32                 byte[] by = File.ReadAllBytes(url);33                 context.Response.Length = by.Length;34                 context.Response.Body = by;35 36             }37             socket.Send(context.Response.Head);38             socket.Send(context.Response.Body);39         }40     }
HttpApplication类

整个请求的模型基本上就差不多完成了,如果是请求的动态文件b.aspx,那么这个b.cs文件需要实现IHttpHandel接口,同时在规定的方法里面进行处理,代码如下:

1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7  8 namespace IIS_Two 9 {10     public class b:IHttpHandel11 12     {13         public void ProcessRequest (HttpContext context)14         {15         //读取模板HTML文件16             string html = File.ReadAllText("temp.html");17             string temp = "
{0}
";18 //读取文本文件类容,拼接一个table表格19 using (StreamReader reader = new StreamReader("1.txt"))20 {21 string str = "";22 List
list = new List
();23 while ((str = reader.ReadLine()) != null)24 {25 string[] strs = str.Split(':');26 list.Add("" + strs[0] + "" + strs[1] + "");27 28 }29 temp = string.Format(temp, string.Join("", list));30 }31 //模板内容的替换32 html = html.Replace("$body", temp);33 byte[] by = Encoding.UTF8.GetBytes(html);34 context.Response.Length = by.Length;35 context.Response.Body = by;36 }37 }38 }
b.cs文件,对应b.aspx资源

附上b.cs中用到的一个HTML模板和一个txt文件

1  2  3  4  5     
6 7 8 9 $body10 11
temp.html
1 aaa:222 bbb:233 ccc:18
1.txt

整个简单的模拟就完成了,bug很多,这不重要。如果请求一个简单的html页面或者是jpg等图片都能够成功,当然这些文件要存在代码中所写的目录下面才行

 

转载于:https://www.cnblogs.com/qigang/p/3918270.html

你可能感兴趣的文章
NYOJ-613//HDU-1176-免费馅饼,数字三角形的兄弟~~
查看>>
graphite custom functions
查看>>
ssh无密码登陆屌丝指南
查看>>
一个自己写的判断2个相同对象的属性值差异的工具类
查看>>
[CF803C] Maximal GCD(gcd,贪心,构造)
查看>>
oracle连接的三个配置文件(转)
查看>>
Java 8 中如何优雅的处理集合
查看>>
[HNOI2012]永无乡 线段树合并
查看>>
Centos下源码安装git
查看>>
gulp-rev-append md5版本号
查看>>
IO流之File类
查看>>
sql 基础语句
查看>>
CF717A Festival Organization(第一类斯特林数,斐波那契数列)
查看>>
控件发布:div2dropdownlist(div模拟dropdownlist控件)
查看>>
Oracle composite index column ordering
查看>>
kaggle竞赛
查看>>
区块链入门教程
查看>>
npm常用命令
查看>>
南海区行政审批管理系统接口规范v0.3(规划)4.2.【queryExpireList】当天到期业务查询...
查看>>
[置顶] 细说Cookies
查看>>