使用C#HttpListener处理多个请求

使用C#HttpListener处理多个请求,c#,httplistener,C#,Httplistener,我有一个.NET Windows服务,它生成一个线程,基本上只是充当一个HttpListener。这在同步模式示例中运行良好 private void CreateLListener() { HttpListenerContext context = null; HttpListener listener = new HttpListener(); bool listen = true; while(listen) { try

我有一个.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-
。据我所知,它这样做是为了弄清楚媒体容器是什么

在读取了一个“块”(或者如果读取的数据足以确定媒体类型)之后,它会发出另一个请求(来自不同的客户端套接字编号),请求的范围为:字节=X-Y。在本例中,Y是第一个响应中返回的内容长度,X比该长度小250000字节(使用IIS作为测试发现)。在这个阶段,它将获得最后一个“块”,以查看它是否可以获得媒体时间戳来测量长度

读了之后,它发出另一个请求,请求
范围字节=0-
(来自另一个套接字编号),以正确地开始流媒体文件

但是,在任何时候,如果客户机用户执行“跳过”操作,则会发送另一个请求(来自另一个套接字编号),其中Z是媒体文件中要跳转到的位置

我不太擅长HTTP,但据我所知,我需要使用多个线程来处理每个请求/响应,同时允许原始的
HttpListener
返回侦听。我做了大量的搜索,但找不到一个似乎合适的模型

编辑:

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


您需要使用异步方法才能处理多个请求。因此,您将使用e
BeginGetContext
EndGetContext
方法

看一看

如果应用程序应该阻塞,那么同步模型是合适的 等待客户端请求时,如果您只想处理一个请求 *一次请求*。使用同步模型,调用GetContext 方法,它等待客户端发送请求。该方法返回 出现HttpListenerContext对象时,向您发送一个HttpListenerContext对象以供处理


如果您需要BeginGetContext的更简单的替代方案,那么您可以只在线程池中对作业进行排队,而不是在主线程上执行它们。例如:

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

如果您来自未来,并试图使用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...
}
公共异步任务侦听(字符串前缀、int-maxConcurrentRequests、CancellationToken令牌)
{
HttpListener=新的HttpListener();
listener.Prefixes.Add(前缀);
listener.Start();
var requests=newhashset();
对于(int i=0;i
Async的工作原理与sync不同(显然)。呼叫begin会立即返回,因此您需要处理这个问题,因此大多数应用程序都有某种waitone。但这不会阻碍。调用begin时指定的回调将在新线程上执行。在那里,你叫结束,然后再叫开始,继续倾听&然后你就开始工作。新的请求将在新线程上处理,直到您决定停止侦听为止。@MisterSquonk很高兴它对您有效。我们这里不给鱼,但教钓鱼。:)这是一个非常好的方法,但掌握异步编程将更好地为您服务如果您关心ProcessRequestAsync的异常,并且您应该关心,请不要忘记在else分支中调用t.Wait()。总而言之,我喜欢这种方法+1。另一个问题是,只有当其中一个WhenAny任务完成时,才会检查WhenAny条件。您能否详细说明为什么只有在WhenAny出现问题时才检查@frast?@Light迷宫取消只有在收到请求后才会发生。如果没有请求,则当没有请求传入时,任何人都可以永久阻止。您可以使用token.throwifcancellationrequest()添加try/catch;在while循环中。然后处理OperationCanceledException,之后,while循环应该退出,因为请求了取消。