65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 可自定义嵌入式 HTTPServer

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (10投票s)

2007年9月12日

CPOL

3分钟阅读

viewsIcon

108789

downloadIcon

2789

一个可定制的 C# 嵌入式 HTTPServer。

Screenshot - screenshot2.jpg

引言

本文介绍了如何使用完全用 C# 编写的小型 HTTP 服务器库,该库可以集成到您自己的应用程序中使用。此库的目的是为开发人员提供一种简单易用且灵活的方式,根据请求的 URI 和/或应用程序的当前状态动态生成 HTTP 响应。

背景

该库由 Hybrid GeoTools 开发,用作集成 Web 服务器,为 Google Earth 提供动态数据。虽然乍一看处理 Google Earth 的请求是一项简单的任务,但事实证明,不正确地处理 HTTP 协议可能会导致意想不到的结果。例如,不正确地处理 Connect 标头会导致 Google Earth 重用连接,而服务器实际上正在等待新的连接。结果,请求根本没有被处理。

因此,开发了 HybridDSP.Net 库。目前,该库仅包含 HTTPServer,但将来可能会添加更多服务。

设计

该库公开了四个类和两个接口

  • HTTPServer - 这个类是实际的服务器。它管理连接、会话和请求。它将请求的处理委托给符合 IHTTPRequestHandler 接口的请求处理程序对象。此对象是通过一个请求处理程序工厂获得的,该工厂作为 HTTPServer 的构造器的参数之一传递。此工厂必须符合 IHTTPRequestHandlerFactory 接口。
  • HTTPServerRequest - 此类表示客户端到服务器的请求。请求处理程序工厂可以根据从请求获得的信息实例化请求处理程序。一旦请求处理程序被实例化,它将被用来处理请求。如果请求包含任何数据,可以从请求中获得一个 Stream 来获取数据(并执行任何需要执行的操作)。
  • HTTPServerResponse - 此类表示从服务器到客户端的响应。默认情况下,它被初始化为返回 HTTP OK。正确设置所有标头后,可以通过将标头发送到客户端来获得一个 Stream。响应的主体可以写入到这个 Stream 中。
  • IHTTPRequestHandler - 此接口定义了任何请求处理程序需要遵守的契约。只定义了一个方法
  • public interface IHTTPRequestHandler
    {
        void HandleRequest(HTTPServerRequest request, HTTPServerResponse response);
    }
    
  • IHTTPRequestHandlerFactory - 此接口定义了任何请求处理程序工厂需要遵守的契约。同样,只定义了一个方法
  • public interface IHTTPRequestHandlerFactory
    {
        IHTTPRequestHandler CreateRequestHandler(HTTPServerRequest request);
    }
    

使用代码

首先,至少需要定义一个请求处理程序才能做任何事情。

class DateTimeHandler : IHTTPRequestHandler
{
    public void HandleRequest(HTTPServerRequest request, HTTPServerResponse response)
    {
        if (request.URI == "/")
        {
            /**
             * In this example we'll write the body into the
             * stream obtained by response.Send(). This will cause the
             * KeepAlive to be false since the size of the body is not
             * known when the response header is sent.
             **/
            response.ContentType = "text/html";
            using (Stream ostr = response.Send())
            using (TextWriter tw = new StreamWriter(ostr))
            {
                tw.WriteLine("<html>");
                tw.WriteLine("<head>");
                tw.WriteLine("<title>Date Time Server</title>");
                tw.WriteLine("<meta http-equiv=\"refresh\" content=\"2\">");
                tw.WriteLine("</header>");
                tw.WriteLine("<body>");
                tw.WriteLine(DateTime.Now.ToString());
                tw.WriteLine("</body>");
                tw.WriteLine("</html>");
            }
        }
        else
        {
            response.StatusAndReason = HTTPServerResponse.HTTPStatus.HTTP_NOT_FOUND;
            response.Send();
        }
    }
}

这个处理程序将生成一个 HTML 页面,显示当前日期和时间,并每两秒钟刷新一次。如果请求不是针对根目录,它将返回一个 HTTP NOT FOUND 响应。

接下来,需要定义一个请求处理程序工厂才能使用刚创建的请求处理程序。

class RequestHandlerFactory : IHTTPRequestHandlerFactory
{
    public IHTTPRequestHandler CreateRequestHandler(HTTPServerRequest request)
    {
        return new DateTimeHandler();
    }
}

这个工厂将简单地始终实例化一个 DateTimeHandler。

最后一步是将所有东西连接在一起。为此,必须实例化一个工厂并将其传递给 HTTPServer 对象的构造器。然后,可以简单地启动服务器。

static void Main(string[] args)
{
    RequestHandlerFactory factory = new RequestHandlerFactory();
    HTTPServer server = new HTTPServer(factory, 8080);
    server.Start();

    Console.Write("Press enter to abort.");
    Console.ReadKey();

    server.Stop();
}

现在,打开你最喜欢的 Web 浏览器,浏览到 *https://:8080*,享受你自己的集成 Web 服务器。

历史

  • 2007 年 9 月 12 日 - 首次发布。
  • 2007 年 9 月 13 日 - 更新了截图。
  • 2007 年 11 月 14 日 - 添加了对 IPv6 的支持。
  • 2007 年 11 月 15 日 - 修复了终止服务器线程的问题。
© . All rights reserved.