这一次我们要玩什么?

先声明一下,由于这篇是基础篇主要是通过这篇文章让大家对使用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. jiekou

    接口 新的接口 package cn.eangaie.jingdong.controller;   import cn.eangaie.jingdong.entity.Result; import c ...

  2. [转]Linux下查看CPU信息、机器型号等硬件信息

    From: http://www.jbxue.com/LINUXjishu/14582.html 查看CPU信息(型号) : # cat /proc/cpuinfo | grep name | cut ...

  3. No Spring WebApplicationInitializer types detected on classpath异常的解决

    1.问题描述,当配置成 时,通过地址栏访问默认路径的index.jsp报404错误,如果手动在浏览器输入“http://localhost:8080/index.jsp”,则出现源码文件,然后观察ec ...

  4. python统计磁盘使用情况

    #coding:utf-8import os; def SortList(item):    return item[1]; def ReadSize(fileName):    return flo ...

  5. 4518: [Sdoi2016]征途

    Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜 ...

  6. koa2怎么自定义一个中间件

    首先定义一个方法 function test(ctx){ global.console.log('m1') } 把这个中间件导出去 module.exports=function(){ return ...

  7. docker常用命令(一)

    1. docker命令 docker images //查看本地镜像 docker rmi 镜像名称:标签名称 //删除一个镜像 docker rm 容器ID //删除一个容器 docker comm ...

  8. git checkout -b

    创建分支: $ git branch mybranch切换分支: $ git checkout mybranch创建并切换分支: $ git checkout -b mybranch 更新master ...

  9. TensorFlow Activation Function 1

    部分转自:https://blog.csdn.net/caicaiatnbu/article/details/72745156 激活函数(Activation Function)运行时激活神经网络中某 ...

  10. ruby安装及webStorm配置SCSS

    sass安装: 步骤:(window系统) 1.下载RubyInstaller(v2.4.3),运行安装,基本直接next安装,不过有个add to PATH的选项一定要勾选,这样就不用配置环境变量. ...