【问题标题】:C# and running of HttpListener in backgroundC# 和在后台运行 HttpListener
【发布时间】:2012-02-23 15:17:28
【问题描述】:

我创建了简单的HttpListener,它侦听端口 9090,并根据请求的 URL 将一些信息写入控制台。

但我被困住了:(我想到了多线程、基于事件的系统,但我没能用它做任何事情。

这是我作为单独的控制台应用程序启动的侦听器的代码:

string urlTemplate = String.Format("/prefix/{0}/suffix", id);
string prefix = String.Format("http://localhost:9090/");

HttpListener listener = new HttpListener();
listener.Prefixes.Add(prefix);

listener.Start();

Console.WriteLine("Listening to {0}...", prefix);

while (true)
{
    HttpListenerContext context = listener.GetContext();
    HttpListenerRequest request = context.Request;

    //Response object
    HttpListenerResponse response = context.Response;

    //Construct response
    if (request.RawUrl.Contains(urlTemplate) && request.HttpMethod == "POST")
    {
         string requestBody;
         Stream iStream = request.InputStream;
         Encoding encoding = request.ContentEncoding;
         StreamReader reader = new StreamReader(iStream, encoding);
         requestBody = reader.ReadToEnd();

         Console.WriteLine("POST request on {0} with body = [{1}]", request.RawUrl, requestBody);

         response.StatusCode = (int)HttpStatusCode.OK;

         //Return a response
         using (Stream stream = response.OutputStream) { }
     }
     else
     {
         response.StatusCode = (int)HttpStatusCode.BadRequest;
         Console.WriteLine("Invalid HTTP request: [{0}] {1}", request.HttpMethod, request.Url);
         using (Stream stream = response.OutputStream) { }
     }
}

我决定将它用作单元测试的实用程序(也许在其他地方)。因此,当测试开始时,我需要配置侦听器,运行它,然后发出一些请求并接收信息(侦听器之前向控制台写入的信息),并在测试结束时停止侦听器。

我的主要想法是将这个侦听器封装到单独的类 MyHttpListener 中,该类具有以下方法:StartListener()StopListener()

但是当我调用StartListener() 时,我的测试因为无限的while 循环而冻结。我试图创建单独的后台线程或基于事件的系统,但我缺乏使用它们的经验,阻止了我这样做。我已经花了很多时间试图找到解决方案,但都是徒劳的。

希望你能帮我找到解决这种琐碎任务的方法。

提前致谢。

【问题讨论】:

    标签: c# multithreading events httplistener


    【解决方案1】:

    响应者的一个变体(似乎他删除了他的帖子)看起来不错,但它对我不起作用。我试图修复它以使其开始工作,但最后该变体让我知道如何解决问题 - 使用多线程和事件:)

    这是我现在所拥有的,它可以工作:

    public delegate void HttpListenerRequestHandler(object sender, HttpListenerEventArgs e);
    public event HttpListenerRequestHandler OnCorrectRequest;
    

    ...

    if(OnCorrectRequest != null)
        OnCorrectRequest(this, new HttpListenerEventArgs(response));
    lock (threadLock)
    {
        Console.WriteLine("POST request on {0} with body = [{1}]", request.RawUrl, requestBody);
    }
    

    ...

    public class HttpListenerEventArgs : EventArgs
    {
        public readonly HttpListenerResponse response;
        public HttpListenerEventArgs(HttpListenerResponse httpResponse)
        {
            response = httpResponse;
        }
    }
    

    为了在主线程中接收来自 HttpListener 的详细响应,我使用以下内容:

    private HttpListenerResponse response;
    
    public void HttpCallbackRequestCorrect(object sender, HttpListenerEventArgs e)
    {
        response = e.response;
        Console.WriteLine("{0} sent: {1}", sender, e.response.StatusCode);
    }
    

    不幸的是,我遇到了以下我不知道如何处理的异常:

    System.Net.HttpListenerException:由于线程退出或应用程序请求,I/O 操作已中止 在 System.Net.HttpListener.GetContext()

    【讨论】:

    • 我使用以下 SO 问题的答案中的代码作为我的基础,到目前为止它运行良好。我对我得到的表现印象深刻。在我的笔记本电脑上,我能够使用单线程测试器每秒处理大约 130-200 个请求,同时从 5 个简单负载测试线程中的每一个线程处理大约 20 个请求。在这些测试中,服务器代码使用了我大约 12% 的 CPU。 stackoverflow.com/questions/5895063/…
    猜你喜欢
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多