我有一个.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作为测试发现)。在这个阶段,它正在获得最后一个“块”,看它是否可以获得媒体时间戳来衡量长度。
阅读完之后,它会使用Range bytes=0-
(来自另一个套接字号)发出另一个请求,以便开始正确地传输媒体文件。
但是,在任何时候,如果客户端的用户执行“跳过”操作,则它会发送另一个请求(来自另一个套接字号)Range bytes=Z-
,其中Z是要跳转到媒体文件的位置
我对HTTP的东西不是很好,但据我所知,我需要使用多个线程来处理每个请求/响应,同时允许原始HttpListener
返回监听。我做了很多搜索,但找不到合适的模型。
修改
感谢Rick Strahl提供以下示例,我能够根据自己的需要进行调整......
Add a Web Server to your .NET 2.0 app with a few lines of code
答案 0 :(得分:16)
如果您需要一个更简单的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
}
答案 1 :(得分:11)
您需要使用异步方法才能处理多个请求。因此,您将使用e BeginGetContext
和EndGetContext
方法。
看看here。
如果您的应用程序应该阻止,则同步模型是合适的 在等待客户请求时,如果您只想处理一个 * 一次请求 *。使用同步模型,调用GetContext 方法,等待客户端发送请求。该方法返回 一个HttpListenerContext对象,供您在发生时进行处理。
答案 2 :(得分:9)
如果您来自未来并尝试使用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...
}