在 500 行以内构建一个微型 Web 服务器






4.88/5 (31投票s)
这个微型 Web 服务器可以被需要提供专用网页的应用程序托管。
引言
最初,我对编写一个简单的 Web 服务器需要做什么很感兴趣。但随着我的进展,我意识到一个微型 Web 服务器对于许多需要提供专用网页的应用程序来说非常有用,而且编写 ASP.NET 应用程序的开销是不必要的(或者无法托管 ASP.NET 的地方)。
一个很好的例子是新闻聚合器,它提供一个包含当前新闻源的单一页面。这个项目就包含一个这样的例子。
更新(2013 年 7 月):根据要求,我添加了对 POST
命令的处理。
Using the Code
应用程序的核心是 TinyServer
类。这个类提供了一个简单的 Web 服务器,仅支持 GET
请求(没有表单),并从目录中提供网页。
要运行示例 Web 服务器,您需要构建 WebServer
项目并配置其设置:
WebRoot : "E:\src\DotNet\WebServer\root" <!-- location of the web pages to serve -->
DefaultPage :"default.html" <!-- name of the default page -->
TemplatePath: "E:\src\DotNet\WebServer\html" <!-- location of special templates -->
Port : 81" <!-- Port to server on -->
LogFile : "" <!-- filepath, set to "" for console logging -->
LogLevel : "All" <!--All, Warning, Error, None -->
一旦 WebServer
应用程序启动,它会实例化 TinyServer
并调用 Run()
。这会在一个单独的线程中启动服务器。调用 Stop()
会终止该线程。
构建您自己的 Web 服务器
很可能,您想构建自己的此 Web 服务器版本。您需要继承 TinyServer
然后重写必要的函数。最重要的要重写的方法是 doGet()
。在此方法中,您可以询问 GET
命令并返回任何必要的内容。
这是处理 GET
命令的默认实现
protected virtual void doGet(string argument)
{
string url = getUrl(argument);
if (url.StartsWith("/"))
url = url.Substring(1);
if (url.Length == 0)
url = defaultPageName;
string path = Path.Combine(webRootPath, url);
if (File.Exists(path))
{
sendOk();
sendfile(path);
}
else
sendError(404, "File Not Found");
}
要处理 POST
命令,有一个 doPost
函数可以重写。目前,它做得很少
protected virtual void doPost(string argument, string Content)
{
log(LogKind.Informational, "Post Data: '{0}'", Content);
sendOk();
}
如您所见,post 的内容可用作 string
。
要实现您的版本,可以使用许多实用函数
string getUrl(string argument)
接受doGet
的命令参数并提取 URLstring [] urlArgs
返回 URL 之后的参数列表sendOK()
发送 OK 标头;在发送任何 HTML 之前,这是必要的sendError(int errornr, string errorMsg)
发送错误而不是 OKsendString(string)
发送一条消息sendFile(path)
发送整个文件sendTemplate (templateName)
发送模板目录中的文件
RssAggregator 示例应用程序
为了演示这种能力,我编写了一个简单的新闻聚合器,它定期从源下载 RSS 提要。
RssAggregator
做两件事
- 下载并保持更新选定的 RSS 提要列表
- 运行一个 Web 服务器,该服务器返回一个包含提要详细信息的网页
第一部分使用由 smallguy78 创建的 RssReader
类。它在自己的线程中运行,并且一旦当前副本超过一小时就会下载提要。
第二部分由一个名为 AggServer
的 TinyServer
子类实现。AggServer
仅返回一个包含新闻提要摘要和文章链接的页面。所以 doGet()
相当简单
protected override void doGet(string argument)
{
this.sendOk();
this.sendString(writeLinkPage());
}
创建网页的智能在于 writeLinkPage()
方法,该方法又依赖于辅助函数 RssReader.CreateHtml()
。整个示例(不包括 RssReader
)仅需要 80 行代码。
关注点
感谢 smallguy78,我使用了他的 RssReader
代码。您可以在此 RSS 阅读器文章中找到更多相关信息。