使用C#HttpListener处理多个请求
我有一个.NET Windows服务,它生成一个线程,基本上只是充当一个使用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
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循环应该退出,因为请求了取消。