【轮子狂魔】抛弃IIS,向天借个HttpListener - 基础篇(附带源码)
这一次我们要玩什么? |
先声明一下,由于这篇是基础篇主要是通过这篇文章让大家对使用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
最新文章
- 百度地图API示例之设置地图显示范围
- Mybatis choose (when, otherwise)标签
- 选择屏幕(Selection Screen)
- SharpMap V1.1 For Web教程系列之——前言
- UVa11404 - Palindromic Subsequence(区间DP+打印路径)
- 替换SQL Server数据库中所有表的所有字段的某些内容
- javascript知识图谱
- NetAnalyzer笔记 之 七 NetAnalyzer2016使用方法(1)
- NHibernate3剖析:Configuration篇之SessionFactory lambda配置
- socket之解决粘包方法
- SQL 高效运行注意事项(二)
- MyDAL - .IsExistAsync() 使用
- python基础--numpy.dot
- 使用HBuilder+MUI+Flask后端服务器框架+Mongodb数据库开发手机APP
- C# Json处理相关
- a标签实现锚点功能
- Linux 用top命令查看CPU和内存使用情况
- CF 2B The least round way DP+Math
- GCD 与 LCM UVA - 11388
- Advising controllers with the @ControllerAdvice annotation