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

1.服务器简单界面如图所示  ()

   1.访问静态页面的时候    http://127.0.0.1:8088/web/1.html 
 
  2.访问动态页面,例如 http://127.0.0.1:8088/Pages/index.aspx
 
项目文件布局:
 
各个类之间的关系(简单):
 
1.可以更改服务器IP地址已经端口
2.点击启动服务器的时候,显示服务器已经启动,同时利用socket进行循环监听
3.利用浏览器访问服务器下面的网页的时候,就显示少量的响应报文头跟响应报文体
 
二、需要用到的知识点
  1. socket进行浏览器与服务器端的通讯
  2. 浏览器与服务器的get与post相关内容
  3. asp.net框架处理流程以及aspx页面生命周期
  4. 接口与工厂

项目步骤

    1. 新建项目,创建一个winform程序,同时创建好相关的控件,点击启动服务器,在窗体初始化的时候,加入下列代码,TextBox.CheckForIllegalCrossThreadCalls = false;目的就是为了显示请求报文的消息,textbox控件新建一个线程来接收,而不用窗体的主线程;
    2. 点击启动的时候 1.新建一个SocketServer类(本质是一台服务器),然后server.start()启动服务器,不停监听来自浏览器的访问页面请求
    3. 这样我们先新建一个
      SocketServer类
      类,因为要用到线程,socket,以及端口等,先引入命名空间

      ,然后创建相关的属性已经socket对象

      ,同时创建构造函数,目的在form传入输入的IP地址,端口,以及显示消息的方法

      ,接下来写一个Start()方法
      因为线程创建的时候要传入一个方法或者是委托,那我就新建一个方法吧,用来循环接收客户端(浏览器)发来的信息 这时接收用户端也要新建一个线程,同时传入一个receiveMsg方法,传入的是什么?传入就是客户端socekt对象,下面又来创建receiveMsg方法接下来定义PR方法,根据ASP.NET框架处理机制,是交由ISAPIRuntime处理
    4. 新建一个ISAPIRuntime类,其实它也不自己出来requestMessage,交由HttpRuntime处理
    5. 新建HttpRuntime类,根据ASP.NET框架处理机制,首先创建上下文对象HTTPContext,(截图)
    6. 新建HttpContext类,根据我们创建HttpRequest、HttpResponse、HttpServerUtility、interface IHttpHandle 这些类和接口,作用分别是请求上下文对象,响应上下文对象,Server属性,接口是给后面的httpApplication,动态和静态处理页面的类来继承,目的只有一个,通过反射,谁创建了接口,他就是那个类的对象,也就是对应着是动态页面,还是静态页面。
    7. HttpContext 类:
    8. HttpRequest 类:定义httpMoethod、Url、HttpVersion、UrlExtention四个属性,同时利用构造函数初始化HttpRequest对象
    9. HttpResponse 类:
    10. HttpRequest _request; //根据请求报文,创建响应的响应报文
              Dictionary <int , string> statuDic = new Dictionary < int, string >();//服务器状态码 如404
              System.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;
       
              }
          }
       
    11. HttpServerUtility 类
    12. 创建上面的类完毕之后,回到HttpContext类,代码不多,引入,同时做好属性封装之后,在构造函数里面进行初始化
    13. 这样的话我们的httpContext对象就创建完毕,根据,我们回到HttpRuntime类,我们创建一个HttpApplicationFactory 工厂类,同时还要创建HttpApplication类,前面是一个工厂类,后面才是我们创建HttpApplication对象,开始跑我们的事件管道
    14. HttpApplicationFactory  类
    15. HttpApplication 类:要继承IHttpHandle接口,实现接口的PR方法,这时候就真正来到我们的事件管道,因为ASP.NET框架有19个事件,实现起来十分复杂,因此在这里我只是简单地执行第8个事件,还有是11跟12个事件之间的PR方法,在第8个事件管道的时候,创建页面类对象,考虑到页面有动态页面跟静态页面,创建的依据就是context.request发来的UrlExtention,因此我创建一个PageProcessFactory页面类工厂,举例有三个页面类对象
    16. PageProcessFactory 类 同时创建者三个类,都要继承IHttpHandle接口,实现PR方法
    17. HttpProcessImg 图片生成生成类
    18. HttpProcessstatic 静态页面生成类
    19. HttpProcessDyn 动态页面生成类
    20. 上面的页面类创建完成后,回到PageProcessFactory工厂类,根据context.request.UrlExtention来创建相应的页面类对象,存到handle中
    21. 这样的话页面类对象创建完成,我们再次回到HttpApplication这个类,执行PageProcessFactory工厂的方法,得到页面类对象,同时进行事件管道的方法,这里只是写第8个事件管道跟11与12事件管道的内容
    22. 执行完事件管道之后,也就是执行完httpcontext,再次回到HttpRuntime类,这时就可以将响应报文respon发回给ISAPIRuntime类,再由这个类返回给SocketServer服务器
    23. 这时就基本完成了浏览器请求服务器上面的网页,回到SocketServer服务器上,将请求报文头显示出来
    24. 回到winform,
    25. 这样我们就差不多完成了自己写的小小的IIS服务器,将我们自己写好的html页面文件复制到项目中,这里有个小小细节要注意,因为运行的时候程序是在bin/debug里面运行,因此右击随便一个文件--属性这样文件就自动复制到bin目录下面,程序就会找到文件

自己动手写一个简单的(IIS)小型服务器的更多相关文章

  1. 动手写一个简单版的谷歌TPU-矩阵乘法和卷积

    谷歌TPU是一个设计良好的矩阵计算加速单元,可以很好的加速神经网络的计算.本系列文章将利用公开的TPU V1相关资料,对其进行一定的简化.推测和修改,来实际编写一个简单版本的谷歌TPU.计划实现到行为 ...

  2. 动手写一个简单版的谷歌TPU-指令集

    系列目录 谷歌TPU概述和简化 基本单元-矩阵乘法阵列 基本单元-归一化和池化(待发布) TPU中的指令集 SimpleTPU实例: (计划中) 拓展 TPU的边界(规划中) 重新审视深度神经网络中的 ...

  3. 动手写一个简单的Web框架(模板渲染)

    动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...

  4. 动手写一个简单的Web框架(Werkzeug路由问题)

    动手写一个简单的Web框架(Werkzeug路由问题) 继承上一篇博客,实现了HelloWorld,但是这并不是一个Web框架,只是自己手写的一个程序,别人是无法通过自己定义路由和返回文本,来使用的, ...

  5. 动手写一个简单的Web框架(HelloWorld的实现)

    动手写一个简单的Web框架(HelloWorld的实现) 关于python的wsgi问题可以看这篇博客 我就不具体阐述了,简单来说,wsgi标准需要我们提供一个可以被调用的python程序,可以实函数 ...

  6. 自己动手写一个简单的MVC框架(第一版)

    一.MVC概念回顾 路由(Route).控制器(Controller).行为(Action).模型(Model).视图(View) 用一句简单地话来描述以上关键点: 路由(Route)就相当于一个公司 ...

  7. 动手写一个简单版的谷歌TPU

    谷歌TPU是一个设计良好的矩阵计算加速单元,可以很好的加速神经网络的计算.本系列文章将利用公开的TPU V1(后简称TPU)相关资料,对其进行一定的简化.推测和修改,来实际编写一个简单版本的谷歌TPU ...

  8. 自己动手写一个简单的MVC框架(第二版)

    一.ASP.NET MVC核心机制回顾 在ASP.NET MVC中,最核心的当属“路由系统”,而路由系统的核心则源于一个强大的System.Web.Routing.dll组件. 在这个System.W ...

  9. 第一个Three.js程序——动手写一个简单的场景

    三维场景基本要素: 步骤: 代码: 源码: <!DOCTYPE html> <html lang="en"> <head> <meta c ...

随机推荐

  1. windows 一个进程可以允许最大的线程数

    默认情况下,一个线程的栈要预留1M的内存空间 而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程 但是内存当然不可能完全拿来作线程的栈,所以实际数目要比这个值要小. 你也 ...

  2. 超级MINI STLINK V2 官方固件自动升级 ST-Link 【worldsing 笔记】

    简介: 支持所有带SWIM接口的STM8系列单片机 支持所有带SWD接口的STM32系列单片机 完全兼容Keil,STVP,STVD,IAR,COSMIC,STM32 ST-LINK Utility! ...

  3. OpenCV学习笔记:MAT解析

    在2001年刚刚出现的时候,OpenCV基于 C 语言接口而建.为了在内存(memory)中存放图像,当时采用名为 IplImage 的C语言结构体,时至今日这仍出现在大多数的旧版教程和教学材料.但这 ...

  4. Mac OS环境下媒体文件分割工具mediafilesegmenter的简单使用(生成M3U8 TS文件)

    mediafilesegmenter是苹果开发的一款用于分割媒体文件的工具,其功能与mediastreamsegmenter相似,但操作更简单. * 具体可以对比博客中的另一篇简介<Mac OS ...

  5. java方法签名

    方法的名字和参数列表称为方法的签名.方法的返回类型不是方法签名的一部分.

  6. Swift基本语法及与OC比较之二

    //MARK:-----------------控制流----------------- //MARK: 1.for - in 循环 ,不用声明Value类型 //for value in 1...6 ...

  7. java异步任务处理

    1.场景 最近做项目的时候遇到了一个小问题:从前台提交到服务端A,A调用服务端B处理超时,原因是前端一次请求往db插1万数据,插完之后会去清理缓存.发送消息. 服务端的有三个操作 a.插DB b.清理 ...

  8. Unity3D-UnityVS的安装和使用

    我们先下载UnityVS,在下面这个网站的资源中搜索一下 http://www.u3dchina.com/portal.php 安装完毕后,执行以下操作 1:打开你的Unity项目 2:在Unity中 ...

  9. PHP str_replace() 函数

    定义和用法 str_replace() 函数使用一个字符串替换字符串中的另一些字符. 语法 str_replace(find,replace,string,count) 参数 描述 find 必需.规 ...

  10. C#自定义控件:WinForm将其它应用程序窗体嵌入自己内部【转载】

    这是最近在做的一个项目中提到的需求,把一个现有的窗体应用程序界面嵌入到自己开发的窗体中来,看起来就像自己开发的一样(实际上……跟自己开发的还是有一点点区别的,就是内嵌程序和宿主程序的窗口激活状态问题) ...