第27篇 重复造轮子---模拟IIS服务器
在写程序的时候,重复造轮子是程序员的一个大忌,很多人对重复造轮子持有反对的态度,但是我觉得这个造轮子的过程,是对于现有的知识的一个深入的探索的过程,虽然我们不可能把轮子造的那么的完善,对于现在有的东西是一个更好的理解和使用。
当你打开一个网页时,你会看到一个html页面的呈现,当然这是一个完整的Http的请求和响应的过程,无非是对HTML+CSS+JS一个综合的产物,在这个过程中浏览器请求数据的过程中会发出一个有一个格式的字符串(基于http协议生成的http请求报文),服务器在接收这样的一段字符的时候会对会这个进行解析,拿到相应的信息,然后根据请求响应的文件结构生成响应数据,当然这个数据发送的格式也是基于Http协议的格式生成的响应报文。然后浏览器在接收到这个数据的时候进行转化和解析,最终生成html的界面展现给客户。
在.Net程序中,如果说浏览器充当的是一个客户端的话,则充当服务器的角色就是IIS了,当你在IIS上发布一个网站的时候,浏览器就能够直接访问你的网站,这个过程是浏览器和IIS服务器之间的一个通信,基于这个过程和上面的理解,我们可以试着去写一个IIS服务器。
对于数据的传输,我想应该都听说过socket,当然也可以用基于TCP,但这个都不重要,重要的是我们怎么根据浏览器的请求,来解析出他想要的数据?下面我们用socket与浏览器进行测试。我们新建一个winform的程序,放上一个按钮和一个text,在按钮的事件中添加一个事件。
private void btnStar_Click(object sender, EventArgs e)
{
var socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
);
socket.Bind(endPoint);
socket.Listen();
var socketProx = socket.Accept();//接收数据
*];
, bytes.Length, SocketFlags.None);
, len);
this.textBox1.Text = httpHeader;
socketProx.Shutdown(SocketShutdown.Both);
socketProx.Close();
socket.Close();
}
当用浏览器访问这个地址和端口的时候,会出现如下的结果:

这个就是我们熟悉的请求报文,其实说白了也就是一段有特定格式的文本字符串。看到这里我们尝试会给浏览器发送一串文本试试,在关闭socket之前发送一个文本。
var httpResponse = "<h1>Hello Http</h1>"; var sentBytes = Encoding.Default.GetBytes(httpResponse); socketProx.Send(sentBytes, , sentBytes.Length, SocketFlags.None);
当我再次用chrome访问的时候:

这个已经把我的数据转化成HTML的语言处理了。当用FireFox去访问的时候:

我们可以发现这个firefox只是把我的数据当成了一个普通的文本并没有解释成html数据,这个是因为我们没有给浏览器一个响应的头信息,就是说你没有告诉浏览器你发送的内容是什么,所以他们才会用自己默认的方式去处理这个信息。下面我们就把响应的头信息给添加上去,看下效果,头信息的获得,可以随意打开一个网站找下。

我们找到如下的头信息:这里我们不需要那么多的信息,只需要一部分,把我们得到后的头信息添加到代码里面,在发送内容前把头信息发送出去,添加如下的代码:
StringBuilder sb = new StringBuilder();
sb.AppendLine("HTTP/1.1 200 OK");
sb.AppendLine("Date:" + DateTime.Now);
sb.AppendLine("Content-Type:" + "text/html");
sb.AppendLine();//很重要
byte[] headerBytes = Encoding.Default.GetBytes(sb.ToString());
socketProx.Send(headerBytes);
在完成后的我们修改的后的代码运行后的结果如下:

这样我们就写一个简单的IIS服务器,我们可以下内容的信息转成文件的格式存储在一个路径下,根据当前请求url取得这个文件,例如我们请求127.0.0.1:50000/1.html,那就找到1.html,读取文件信息然后发送头信息,然后在把内容发送给浏览器。
下面我们对上面的程序进行改写,改成读取文件信息,添加了两个方法如下,改写如下:
private byte[] ResovleHttp(string httpHead)
{
string[] requestLines = httpHead.Split(new string[] { "\r\n" }, StringSplitOptions.None);
].Split(];
].Split(];
var filePath = Application.StartupPath+Path.Combine(requestUrl);
if (File.Exists(filePath))
{
var fileBytes = File.ReadAllBytes(filePath);
return fileBytes;
}
return NotFound();
}
private byte[] NotFound()
{
var strHtml = "<h1>Not Found404</h1>";
return Encoding.Default.GetBytes(strHtml);
}
当我们访问127.0.0.1:50000/1.html的时候我们能够看到我们html里面内容:
当我们没有找到页面的时候,我添加一个未找到的提示信息。

好了,到现在我们已经把基本的原理已经完成了,上面的程序只能支持静态页面的访问,下面我们就要对现在的程序进行改造了。 至于这个改造的过程,我就不细说了,也是能力有限,自己也写好了一个,支持执行后台的代码。程序代码在gitHub上面,地址:https://github.com/fuwei199006/.NetLib/tree/master/IIS%E6%A8%A1%E6%8B%9F
代码结构:

第27篇 重复造轮子---模拟IIS服务器的更多相关文章
- 重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印
重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印 一.引言 桌面端系统经常需要对接各种硬件设备,比如扫描器.读卡器.打印机等. 这里介绍下桌面端 ...
- 重复造轮子系列——基于Ocelot实现类似支付宝接口模式的网关
重复造轮子系列——基于Ocelot实现类似支付宝接口模式的网关 引言 重复造轮子系列是自己平时的一些总结.有的轮子依赖社区提供的轮子为基础,这里把使用过程的一些觉得有意思的做个分享.有些思路或者方法在 ...
- 54 个官方 Spring Boot Starters 出炉!别再重复造轮子了…….
在之前的文章,栈长介绍了 Spring Boot Starters,不清楚的可以点击链接进去看下. 前段时间 Spring Boot 2.4.0 也发布了,本文栈长再详细总结下最新的 Spring B ...
- 避免重复造轮子的UI自动化测试框架开发
一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览 ...
- GitHub Android 最火开源项目Top20 GitHub 上的开源项目不胜枚举,越来越多的开源项目正在迁移到GitHub平台上。基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要。利用这些项目,有时能够让你达到事半功倍的效果。
1. ActionBarSherlock(推荐) ActionBarSherlock应该算得上是GitHub上最火的Android开源项目了,它是一个独立的库,通过一个API和主题,开发者就可以很方便 ...
- 重复造轮子,编写一个轻量级的异步写日志的实用工具类(LogAsyncWriter)
一说到写日志,大家可能推荐一堆的开源日志框架,如:Log4Net.NLog,这些日志框架确实也不错,比较强大也比较灵活,但也正因为又强大又灵活,导致我们使用他们时需要引用一些DLL,同时还要学习各种用 ...
- Light libraries是一组通用的C基础库,目标是为减少重复造轮子而写(全部用POSIX C实现)
Light libraries是一组通用的C基础库,目标是为减少重复造轮子而写实现了日志.原子操作.哈希字典.红黑树.动态库加载.线程.锁操作.配置文件.os适配层.事件驱动.工作队列.RPC.IPC ...
- Meteva——让预报检验不再重复造轮子
更多精彩,请点击上方蓝字关注我们! 检验是什么?****预报准确率的客观表达 说到天气预报,你最先会想到什么? 早上听了预报,带了一天伞却没下一滴雨的调侃? 还是 "蓝天白云晴空万里突然暴风 ...
- 答应我,用了这个jupyter插件,别再重复造轮子了
1 简介 在使用Python.R等完成日常任务的过程中,可能会经常书写同样或模式相近的同一段代码,譬如每次使用matplotlib绘制图像的时候可以在开头添加下面两行代码来解决中文乱码等显示问题: p ...
随机推荐
- HTML5 Canvas、内联 SVG、Canvas vs. SVG
canvas 元素用于在网页上绘制图形. 什么是 Canvas? HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像. 画布是一个矩形区域,您可以控制其每一像素. canv ...
- flex chrome浏览器调试flex程序
flex chrome浏览器调试出现空白的解决方法: 1,为chrome安装flash player,禁用chrome自带的flash player:参考:http://www.jb51.net/ar ...
- WCF服务发布到IIS中去 在WCF调试
第一个WCF程序 1. 新建立空白解决方案,并在解决方案中新建项目,项目类型为:WCF服务应用程序.建立完成后如下图所示: 2.删除系统生成的两个文件IService1.cs与Service1.svc ...
- KVO,看我就够了!
概述 KVO全称Key-Value-Observing,也叫键值监听,是一种观察者设计模式.提供了一种机制,当指定的对象的属性被修改后,对象就会收到一个通知.也就是说每次指定的被观察的对象的属性被修改 ...
- Windows 10 IoT Core环境配置中的那些坑
我使用的设备是Raspberry Pi 3B,想来国内的嵌入式玩具应该还是树莓派最常见吧.这段时间一直在捣鼓Win10 IoT,结果发现,从安装一直到编码调试一路下来全都是坑.写这篇东西一个是为了备忘 ...
- TCP&UDP
TCP(传输控制协议) 建立连接,形成传输数据的通道 在连接中进行大数据传输(数据大小不受限制) 通过三次握手完成连接,是可靠协议,安全送达(三次握手向服务器发送请求,响应请求回复,发送数据) 必须建 ...
- 微信小程序教程(第四篇)
小程序开发基本框架及其限制与优化 开发基本框架(MINA框架) └─ Project-folder/ ·································· 项目所在目录 ├─ page ...
- gulp实时编译less,压缩合并requirejs模块文件
gulp的使用命令简单,就几个,gulp的简单使用教材可以参考一点的gulp使用教材(http://www.ydcss.com/archives/18). 下面就简单的介绍这些命令如何互相配合的完成前 ...
- [CSS3] 学习笔记-HTML与CSS简单页面效果实例
一个简单的首页的设计: html文件: <!doctype html> <html> <head> <meta charset="UTF-8&quo ...
- 深入理解DOM事件类型系列第六篇——加载事件
前面的话 提到加载事件,可能想到了window.onload,但实际上,加载事件是一大类事件,本文将详细介绍加载事件 load load事件是最常用的一个事件,当页面完全加载后(包括所有图像.java ...