首页 文章

使用C#HttpListener处理多个请求

提问于
浏览
14

我有一个.NET Windows服务,它产生一个基本上只是作为 HttpListener 的线程 . 这在同步模式示例中工作正常......

private void CreateLListener()
{
    HttpListenerContext context = null;
    HttpListener listener = new HttpListener();
    bool listen = true;

    while(listen)
    {
        try
        {
            context = listener.GetContext();
        }
        catch (...)
        {
            listen = false;
        }
        // process request and make response
    }
}

我现在遇到的问题是我需要这个来处理多个请求,并让它们同时或至少以重叠的方式响应 .

进一步解释 - 客户端是一个媒体播放器应用程序,它首先通过请求标头属性 Range bytes=0- 请求媒体文件 . 据我所知,它可以解决媒体容器的问题 .

在读取了'chunk'(或者如果它已经读取足以确定媒体类型)之后,它会使用 Range bytes=X-Y 发出另一个请求(来自不同的客户端套接字号) . 在这种情况下,Y是第一个响应中返回的Content-Length,X比该值小250000个字节(使用IIS作为测试发现) . 在这个阶段,它正在获得最后的'chunk',看看它是否可以获得媒体时间戳来衡量长度 .

读完之后,它使用 Range bytes=0- (来自另一个套接字号)发出另一个请求,以开始正确地流式传输媒体文件 .

但是,在任何时候,如果客户端的用户执行'skip'操作,则它会发送另一个请求(来自另一个套接字号),其中_是 Range bytes=Z- ,其中Z是要跳转到媒体文件中的位置 .

我对HTTP的东西不是很好,但据我所知,我需要使用多个线程来处理每个请求/响应,同时允许原始 HttpListener 返回监听 . 我找到一个似乎合适的模型 .

EDIT:

感谢Rick Strahl对以下示例的感谢,我能够根据自己的需要进行调整......

Add a Web Server to your .NET 2.0 app with a few lines of code

3 回答

  • 15

    如果您来自未来并尝试使用async / await处理单个线程的多个并发请求 .

    public async Task Listen(string prefix, int maxConcurrentRequests, CancellationToken token)
    {
        HttpListener listener = new HttpListener();
        listener.Prefixes.Add(prefix);
        listener.Start();
    
        var requests = new HashSet<Task>();
        for(int i=0; i < maxConcurrentRequests; i++)
            requests.Add(listener.GetContextAsync());
    
        while (!token.IsCancellationRequested)
        {
            Task t = await Task.WhenAny(requests);
            requests.Remove(t);
    
            if (t is Task<HttpListenerContext>)
            {
                var context = (t as Task<HttpListenerContext>).Result;
                requests.Add(ProcessRequestAsync(context));
                requests.Add(listener.GetContextAsync());
            }
        }
    }
    
    public async Task ProcessRequestAsync(HttpListenerContext context)
    {
        ...do stuff...
    }
    
  • 11

    您需要使用异步方法才能处理多个请求 . 所以你会使用e BeginGetContextEndGetContext 方法 .

    看看here .

    如果您的应用程序在等待客户端请求时应该阻塞,并且您希望一次只处理一个请求,则同步模型是合适的 . 使用同步模型,调用GetContext方法,该方法等待客户端发送请求 . 该方法返回一个HttpListenerContext对象,以便在发生时进行处理 .

  • 8

    如果您需要一个更简单的BeginGetContext替代方法,您只能在ThreadPool中排队作业,而不是在主线程上执行它们 . 像这样:

    private void CreateLListener() {
        //....
        while(true) {
            ThreadPool.QueueUserWorkItem(Process, listener.GetContext());    
        }
    }
    void Process(object o) {
        var context = o as HttpListenerContext;
        // process request and make response
    }
    

相关问题