这一次我们要玩什么?

先声明一下,由于这篇是基础篇主要是通过这篇文章让大家对使用HttpListener响应Http请求有个大概了解,所以正式的花样轮子在下一篇推出,敬请期待 ^_^

嗯哼,还有,我标题党了一下,看完我这个系列的话,在特定场景下可抛弃IIS,但如果完全抛弃IIS就不要想咯 ^_^

HttpListener:提供一个简单的、可通过编程方式控制的 HTTP 协议侦听器。(好吧,我承认这句是从MSDN上抄过来的)

既然引子出来了,说明我们要开始玩Http请求了。

那么我们基础篇要做的是,如何把一个 html 文件从服务器返回给客户端。

一个Http请求我们需要做些什么?

1.监听一个地址前缀,如:http://localhost/

2.解析Url

3.执行Url所代表的指令

4.返回执行结果

监听一个Http请求

下面贴出的是主要的代码,实际源码中做了一些其他的处理,比如多线程防止界面卡死、HttpListener运行环境检测、资源释放、容错等等。

                 HttpListener server = new HttpListener();
try
{
MakeHttpPrefix(server);
server.Start();
}
catch (Exception ex)
{
Logger.Exit("无法启动服务器监听,请检查网络环境。");
} IAsyncResult result = null;
while (!_terminated)
{
while (result == null || result.IsCompleted)
{
result = server.BeginGetContext(new AsyncCallback(ProcessHttpRequest), server);
}
_ready = true;
Thread.Sleep();
} server.Stop();
server.Abort();
server.Close();
解析Url

解析Url时需要做几个事情:

1.Url的长度限制

2.是否包含特殊字符

3.拆分指令与参数

     /// <summary>
/// Url辅助类:对Url进行初步的解析
/// </summary>
public class UrlHelper
{
const int MAX_URI_LENGTH = ;
string _scriptName = string.Empty;
CommandResult _parseResult = CommandResult.Success;
NameValueCollection _parameters = new NameValueCollection();
char[] _uriInvalidChar = new char[] { '/', '\\' };
char[] _pathInvalidChar = new char[] { '/', '\\', ':', '*', '?', '\"', '<', '>', '|' };
public Uri _uri = null; public string ScriptName
{
get { return _scriptName; }
} public NameValueCollection Parameters
{
get { return _parameters; }
} public CommandResult ParseResult
{
get { return _parseResult; }
} public UrlHelper(Uri originalUri)
{
_uri = originalUri; if (IsUriLengthError())
{
return;
} if (CheckPathAndQuery())
{
ParsePathAndQuery();
}
} private bool IsUriLengthError()
{
if (_uri == null || _uri.ToString().Length > MAX_URI_LENGTH)
{
_parseResult = CommandResult.UrlTooLong;
return true;
}
return false;
} private bool CheckPathAndQuery()
{
string pathAndQuery = _uri.PathAndQuery.Substring(); if (IsUrlInvalidChar(pathAndQuery))
{
return false;
} if (pathAndQuery.IndexOfAny(_uriInvalidChar) >= )
{
_parseResult = CommandResult.UrlInvalidChar;
return false;
}
else if (pathAndQuery.Length == )
{
_parseResult = CommandResult.NoExistsMethod;
return false;
} string[] splitPathAndQuery = new string[] { };
if (IsFileNameInvalidChar(pathAndQuery, splitPathAndQuery))
{
return false;
} return true; } private bool IsFileNameInvalidChar(string pathAndQuery, string[] splitPathAndQuery)
{
splitPathAndQuery = pathAndQuery.Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries);
if (splitPathAndQuery[].IndexOfAny(_pathInvalidChar) >= )
{
_parseResult = CommandResult.FileNameInvalidChar;
return true;
}
return false;
} private bool IsUrlInvalidChar(string pathAndQuery)
{
if (pathAndQuery.IndexOfAny(_uriInvalidChar) >= )
{
_parseResult = CommandResult.UrlInvalidChar;
return true;
}
return false;
} private void ParsePathAndQuery()
{
string[] splitPathAndQuery = _uri.PathAndQuery.Substring().Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries);
SetScriptNameAndParameters(splitPathAndQuery);
} private void SetScriptNameAndParameters(string[] splitPathAndQuery)
{
_scriptName = splitPathAndQuery[]; if (splitPathAndQuery.Length > )
{
_parameters = HttpUtility.ParseQueryString(splitPathAndQuery[], Encoding.UTF8);
}
}
}
执行Url所代表的指令和返回执行结果

1.判断Url的请求文件后缀是否支持

2.检索本地文件

3.如果文件存在则返回文件,不存在则返回异常(此处在后续扩展活增加更多可变性,比如一些动态执行方法等)

PS:由于此处代码涉及几个方法就不贴了,直接看源码吧。(ProcessHttpRequest 方法)

有图有真相

请求一个简单的Hello World的html文件,此处有个细节,就是浏览器会发送ico请求。聪明的你如果想要显示ico应该知道怎么办吧 ^_^

请求一个不支持的后缀,如:htm

下一次我们玩什么?

1.丰富一下请求文件类型

2.支持执行方法的请求

3.在HttpListner里玩一玩LUA脚本

最后,我要放源码了 ^_^

http://git.oschina.net/doddgu/WebServerDemo

【轮子狂魔】抛弃IIS,向天借个HttpListener - 基础篇(附带源码)的更多相关文章

  1. 【轮子狂魔】抛弃IIS,打造个性的Web Server - WebAPI/Lua/MVC(附带源码)

    引言 此篇是<[轮子狂魔]抛弃IIS,向天借个HttpListener - 基础篇(附带源码)>的续篇,也可以说是提高篇,如果你对HttpListener不甚了解的话,建议先看下基础篇. ...

  2. 【轮子狂魔】手把手教你自造Redis Client

    为什么做Redis Client? Redis Client顾名思义,redis的客户端,主要是封装了一些对于Redis的操作. 而目前用的比较广泛的 ServiceStack.Redis 不学好,居 ...

  3. 【轮子狂魔】打造简易无配置的IoC

    如何指定Business Event和Command之间的关系? 既然是基于惯例优先原则,那么我们首先需要定义一个惯例: 1.调度事件和调度处理器之间是一对多关系(多对多的话,相信你看完了以后应该会知 ...

  4. 「造个轮子」——cicada 源码分析

    前言 两天前写了文章<「造个轮子」--cicada(轻量级 WEB 框架)> 向大家介绍了 cicada 之后收到很多反馈,也有许多不错的建议. 同时在 GitHub 也收获了 80 几颗 ...

  5. 【轮子狂魔】手把手教你用JS给博客动态增加目录 - 超级懒人版

    动态显示目录的作用 不用每次写博客的时候繁琐的人工整理目录,又可以动态浮动在右下角,方便快速跳到感兴趣的位置同时也可以快速的对文章内容有一个大概的了解. 实现原理 首先根据个人喜好,我习惯了用 h1 ...

  6. 【轮子狂魔】WeChatAPI 开源系统架构详解

    如果使用WeChatAPI,它扮演着什么样的角色? 从图中我们可以看到主要分为3个部分: 1.业务系统 2.WeChatAPI: WeChatWebAPI,主要是接收微信服务器请求: WeChatAP ...

  7. WebForm(一)——IIS服务器、开发方式和简单基础

    一.B/S和C/S 1.C/S C/S 架构是一种典型的两层架构,其全程是Client/Server,即客户端服务器端架构,其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据 ...

  8. WebForm——IIS服务器、开发方式和简单基础

    一.B/S和C/S 1.C/S C/S 架构是一种典型的两层架构,其全程是Client/Server,即客户端服务器端架构,其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据 ...

  9. CassiniDev源码学习 - 可替代IIS的单机Web Form解决方案

    最近一个项目是将web版的程序,改为单机版.话说这个web版号称当年十几个人用了至少3个月的时间开发,后来三年还不断有修改,而现在要在1个月内由一个人完成,这简直是不可能完成的任务!直觉告诉我,重写肯 ...

随机推荐

  1. jquery ztree的案例,附源代码

    播客:http://itindex.net/detail/46094-jquery-ztree-%E7%A8%8B%E5%BA%8F   源代码: http://download.csdn.net/d ...

  2. amcharts属性

    Amcharts的特点包含: *动画或静态 *价值轴能够扭转 *线性或对数轴的价值尺度 *提前定义或定制的子弹 *定制描写叙述不论什么数据点 *点击栏目/酒吧(可用于钻孔下来图表) *梯度弥漫 *价值 ...

  3. BZOJ2435:[NOI2011]道路修建 (差分)

    Description 在 W 星球上有 n 个国家.为了各自国家的经济发展,他们决定在各个国家 之间建设双向道路使得国家之间连通.但是每个国家的国王都很吝啬,他们只愿 意修建恰好 n – 1条双向道 ...

  4. 「GXOI / GZOI2019」旧词

    题目 确定这不是思博题 看起来很神仙,本来以为是\([LNOI2014]LCA\)的加强版,结果发现一个点的贡献是\(s_i\times (deep_i^k-(deep_i-1)^k)\),\(s_i ...

  5. luogu P2709 小B的询问

    嘟嘟嘟 莫队板子. 记住:删除是先删除再移动,添加是先移动在添加! #include<cstdio> #include<iostream> #include<cmath& ...

  6. python面试题库——1Python基础篇

    第一部分 Python基础篇(80题) 为什么学习Python? 语言本身简洁,优美,功能超级强大,跨平台,从桌面应用,web开发,自动化测试运维,爬虫,人工智能,大数据处理都能做 Python和Ja ...

  7. Kafka设计解析(三)Kafka High Availability (下)

    转载自 技术世界,原文链接 Kafka设计解析(三)- Kafka High Availability (下) 摘要 本文在上篇文章基础上,更加深入讲解了Kafka的HA机制,主要阐述了HA相关各种场 ...

  8. RadioButtonFor值为false.默认选中的问题

    (自己看了下.图片有点宽.显示的不全.可以右键新标签查看) 作为一个新手.今天又开始了mvc的学习之旅.然而学习过程中又遇到了一个奇妙的问题.... 一切按部就班到了这里.注册界面. 一眼看上去就不对 ...

  9. 关于ISP、IAP、DFU和bootloader

    这是嵌入式开发中常用的几个专业术语,其诞生的背景和其具体作用大概如下   在很久很久以前,那是8051单片机流行的时代,做单片机开发都需要一个专用工具,就是单片机的编程器,或者叫烧写器.说“烧”写一点 ...

  10. Apache24 + php5.6.31 +Sql server R2 环境搭建①

    win8(7)x64系统下 :PHP5.5.15 + Apache2.4.10 + SQL server 2008 R2  的配置方法分享给大家,32位的同理,不过下载的软件需要也是32位的. 好久未 ...