自己动手写一个简单的(IIS)小型服务器
因为第一次在博客园发表随笔,不太会用,这个笔记是我之前在印象笔记中写好的,然后直接copy过来,有兴趣自己做一个IIS服务器的小伙伴们可以参照下面的流程做一次,也可以叫我要源代码,不过要做完,我觉得花费一下午的时间必须是要的,完成之后,可能你对ASP.NET框架的具体运作流程会有更加深的了解----源代码是参考邹华栋老师,在此表示感谢
1.服务器简单界面如图所示 ()




- socket进行浏览器与服务器端的通讯
- 浏览器与服务器的get与post相关内容
- asp.net框架处理流程以及aspx页面生命周期
- 接口与工厂
项目步骤
- 新建项目,创建一个winform程序,同时创建好相关的控件,点击启动服务器,在窗体初始化的时候,加入下列代码,TextBox.CheckForIllegalCrossThreadCalls = false;目的就是为了显示请求报文的消息,textbox控件新建一个线程来接收,而不用窗体的主线程;

- 点击启动的时候 1.新建一个SocketServer类(本质是一台服务器),然后server.start()启动服务器,不停监听来自浏览器的访问页面请求
- 这样我们先新建一个
SocketServer类
类,因为要用到线程,socket,以及端口等,先引入命名空间
,然后创建相关的属性已经socket对象
,同时创建构造函数,目的在form传入输入的IP地址,端口,以及显示消息的方法
,接下来写一个Start()方法
因为线程创建的时候要传入一个方法或者是委托,那我就新建一个方法吧,用来循环接收客户端(浏览器)发来的信息
这时接收用户端也要新建一个线程,同时传入一个receiveMsg方法,传入的是什么?传入就是客户端socekt对象,下面又来创建receiveMsg方法
接下来定义PR方法,根据ASP.NET框架处理机制,是交由ISAPIRuntime处理
- 新建一个ISAPIRuntime类,其实它也不自己出来requestMessage,交由HttpRuntime处理

- 新建HttpRuntime类,根据ASP.NET框架处理机制,首先创建上下文对象HTTPContext,(截图)
- 新建HttpContext类,根据
我们创建HttpRequest、HttpResponse、HttpServerUtility、interface IHttpHandle 这些类和接口,作用分别是请求上下文对象,响应上下文对象,Server属性,接口是给后面的httpApplication,动态和静态处理页面的类来继承,目的只有一个,通过反射,谁创建了接口,他就是那个类的对象,也就是对应着是动态页面,还是静态页面。 - HttpContext 类:

- HttpRequest 类:定义httpMoethod、Url、HttpVersion、UrlExtention四个属性,同时利用构造函数初始化HttpRequest对象


- HttpResponse 类:
- HttpRequest _request; //根据请求报文,创建响应的响应报文
Dictionary <int , string> statuDic = new Dictionary < int, string >();//服务器状态码 如404System.Text. StringBuilder sbContent = new StringBuilder(500); //用来接收write()写入的字符串/// <summary>/// 构造函数,初始化服务器状态码/// </summary>/// <param name="request"></param>public HttpResponse(HttpRequest request){this ._request = request;statuDic.Add(200, "OK" );statuDic.Add(302, "Found" );statuDic.Add(404, "File Not Found" );statuDic.Add(500, "Error" );}//刚开始给状态码赋初始值statuCode=200;private int statuCode = 200;/// <summary>/// 状态码,如200/// </summary>public int StatuCode{get { return statuCode; }set { statuCode = value ; }}private string statuStr;/// <summary>/// 状态码对应的应为表示符,如OK,FOUND/// </summary>public string StatuStr{get { return statuStr; }set { statuStr = value ; }}private byte [] content = new byte [0];/// <summary>/// 响应报文的流/// </summary>public byte [] Content{get { return content; }set { content = value ; }}/// <summary>/// 响应报文长度/// </summary>public int ContentLength{get{return content.Length;}}/// <summary>/// 根据请求报文的后缀名,如.jpg对应image/jpeg/// </summary>public string ContenType{get{string contentType = "" ;switch (_request.UrlExtention){case ".jpg" :case ".png" :case ".gif" :contentType = "image/jpeg" ;break ;case ".html" :case ".htm" :contentType = "text/html" ;break ;case ".aspx" :case ".ashx" :case "styd" :contentType = "text/html" ;break ;case ".css" :contentType = "text/css" ;break ;case ".js" :contentType = "application/javascript" ;break ;default :contentType = "text/html" ;break ;}return contentType;}}public string Server{get { return "MyIISServer"; }}/// <summary>/// 服务器响应报文的write()方法,相当于content.Response.Write/// </summary>/// <param name="str"></param>public void Write( string str){sbContent.Append(str);content = System.Text.Encoding .UTF8.GetBytes(sbContent.ToString());}System.Text. StringBuilder sbHead = new StringBuilder(200);/// <summary>/// 组装响应报文体,返回byte数组/// </summary>/// <returns></returns>public byte [] GetResponseByts(){sbHead.AppendLine(_request.HttpVersion + " " + this .StatuCode + " " + this .StatuStr);sbHead.AppendLine( "Server:myWebServer" );sbHead.AppendLine( "Content-Length:" + this.ContentLength);sbHead.AppendLine( "Content-Type:" + this.ContenType + " ;charset=utf-8");sbHead.AppendLine( "" );//头和体之间的空白行byte [] head = System.Text.Encoding .UTF8.GetBytes(sbHead.ToString());byte [] resultByte = new byte[head.Length + ContentLength];head.CopyTo(resultByte, 0);Content.CopyTo(resultByte, head.Length);return resultByte;}}
- HttpServerUtility 类

- 创建上面的类完毕之后,回到HttpContext类,代码不多,引入
,同时做好属性封装之后,在构造函数里面进行初始化
- 这样的话我们的httpContext对象就创建完毕,根据
,我们回到HttpRuntime类,我们创建一个HttpApplicationFactory 工厂类,同时还要创建HttpApplication类,前面是一个工厂类,后面才是我们创建HttpApplication对象,开始跑我们的事件管道 - HttpApplicationFactory 类

- HttpApplication 类:要继承IHttpHandle接口,实现接口的PR方法,这时候就真正来到我们的事件管道,因为ASP.NET框架有19个事件,实现起来十分复杂,因此在这里我只是简单地执行第8个事件,还有是11跟12个事件之间的PR方法,在第8个事件管道的时候,创建页面类对象,考虑到页面有动态页面跟静态页面,创建的依据就是context.request发来的UrlExtention,因此我创建一个PageProcessFactory页面类工厂,举例有三个
页面类对象 - PageProcessFactory 类 同时创建
者三个类,都要继承IHttpHandle接口,实现PR方法 - HttpProcessImg 图片生成生成类

- HttpProcessstatic 静态页面生成类

- HttpProcessDyn 动态页面生成类

- 上面的页面类创建完成后,回到PageProcessFactory工厂类,根据context.request.UrlExtention来创建相应的页面类对象,存到handle中

- 这样的话页面类对象创建完成,我们再次回到HttpApplication这个类,执行PageProcessFactory工厂的方法,得到页面类对象,同时进行事件管道的方法,这里只是写第8个事件管道跟11与12事件管道的内容

- 执行完事件管道之后,也就是执行完httpcontext,再次回到HttpRuntime类,这时就可以将响应报文respon发回给ISAPIRuntime类,再由这个类返回给SocketServer服务器
- 这时就基本完成了浏览器请求服务器上面的网页,回到SocketServer服务器上,将请求报文头显示出来
- 回到winform,

- 这样我们就差不多完成了自己写的小小的IIS服务器,将我们自己写好的html页面文件复制到项目中,这里有个小小细节要注意,因为运行的时候程序是在bin/debug里面运行,因此右击随便一个文件--属性
这样文件就自动复制到bin目录下面,程序就会找到文件
自己动手写一个简单的(IIS)小型服务器的更多相关文章
- 动手写一个简单版的谷歌TPU-矩阵乘法和卷积
谷歌TPU是一个设计良好的矩阵计算加速单元,可以很好的加速神经网络的计算.本系列文章将利用公开的TPU V1相关资料,对其进行一定的简化.推测和修改,来实际编写一个简单版本的谷歌TPU.计划实现到行为 ...
- 动手写一个简单版的谷歌TPU-指令集
系列目录 谷歌TPU概述和简化 基本单元-矩阵乘法阵列 基本单元-归一化和池化(待发布) TPU中的指令集 SimpleTPU实例: (计划中) 拓展 TPU的边界(规划中) 重新审视深度神经网络中的 ...
- 动手写一个简单的Web框架(模板渲染)
动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...
- 动手写一个简单的Web框架(Werkzeug路由问题)
动手写一个简单的Web框架(Werkzeug路由问题) 继承上一篇博客,实现了HelloWorld,但是这并不是一个Web框架,只是自己手写的一个程序,别人是无法通过自己定义路由和返回文本,来使用的, ...
- 动手写一个简单的Web框架(HelloWorld的实现)
动手写一个简单的Web框架(HelloWorld的实现) 关于python的wsgi问题可以看这篇博客 我就不具体阐述了,简单来说,wsgi标准需要我们提供一个可以被调用的python程序,可以实函数 ...
- 自己动手写一个简单的MVC框架(第一版)
一.MVC概念回顾 路由(Route).控制器(Controller).行为(Action).模型(Model).视图(View) 用一句简单地话来描述以上关键点: 路由(Route)就相当于一个公司 ...
- 动手写一个简单版的谷歌TPU
谷歌TPU是一个设计良好的矩阵计算加速单元,可以很好的加速神经网络的计算.本系列文章将利用公开的TPU V1(后简称TPU)相关资料,对其进行一定的简化.推测和修改,来实际编写一个简单版本的谷歌TPU ...
- 自己动手写一个简单的MVC框架(第二版)
一.ASP.NET MVC核心机制回顾 在ASP.NET MVC中,最核心的当属“路由系统”,而路由系统的核心则源于一个强大的System.Web.Routing.dll组件. 在这个System.W ...
- 第一个Three.js程序——动手写一个简单的场景
三维场景基本要素: 步骤: 代码: 源码: <!DOCTYPE html> <html lang="en"> <head> <meta c ...
随机推荐
- Linux Pmap 命令:查看进程用了多少内存
Pmap 提供了进程的内存映射,pmap命令用于显示一个或多个进程的内存状态.其报告进程的地址空间和内存状态信息.Pmap实际上是一个Sun OS上的命令,linux仅支持其有限的功能.但是它还是对查 ...
- UITableView性能优化
关于UITableView的性能优化,网络上也有一些总结.在这里就介绍下我们项目中遇到的问题以及对应的解决方法.相信我们遇到的问题也有一定的普适性,能够作为其他问题的优化方案. Instruments ...
- [css]display: table-cell,用div做分列布局
table-cell我们却能用得到,而且是用它来干一件很重要的事情——多列布局. 多列布局在css中有多重要就不用我说了吧,传统模式下大家都使用float来解决这一问题,但是float写出来的东西代码 ...
- jquery基础篇
1.jquery选择器和css选择器的关系: jquery的选择器是源于css,jquery支持css1和css2的全部和css3 的部分选择器,同时它也有少量独有的选择器. 2.常用jquery选择 ...
- vs之Nuget
1.http://msdn.microsoft.com/zh-cn/magazine/hh547106.aspx 2.在Nuget控制台中安装特定版本: Install-Package <程序包 ...
- Oracle管道函数示例
Oracle的管道函数需要定义下面的三样: Record/Object Type:定义一个Record或Object类型的变量,这个变量用于表示返回结果集的一行数据,有点像C#中的DataRow类. ...
- Attribute特性验证模型model
数据验证我们往往分为前台验证和后台验证,而我们的后台验证每到一个方法中就要去验证一次,这样的代码想想都难以维护,这篇我们这篇文章就是为了解决这样的问题.用attribute 这个特性来解决这样的问题 ...
- SQLite使用教程4 创建数据库
http://www.runoob.com/sqlite/sqlite-create-database.html SQLite 创建数据库 SQLite 的 sqlite3 命令被用来创建新的 SQL ...
- 授予普通域用户远程桌面连接DC/客户端权限
普通域用户通过远程桌面登录DC: 1)将该用户加入到 Remote Desktop Users 组中
- C#-datagridview右键选中行
在datagridview中有时需要在右键点击某行的时候就选中它,那么我们只需要在datagridview的CellMonseDown事件中添加如下代码就行: && e.ColumnI ...