簡體   English   中英

使用C#HttpListener處理多個請求

[英]Handling multiple requests with C# HttpListener

我有一個.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-請求媒體文件。 據我所知,它可以解決媒體容器的問題。

在讀取“塊”之后(或者如果它已經讀取足以確定媒體類型),則它會發出另一個請求(來自不同的客戶端套接字號),其中Range bytes=XY 在這種情況下,Y是第一個響應中返回的Content-Length,X比該值小250000個字節(使用IIS作為測試發現)。 在這個階段,它正在獲得最后一個“塊”,看它是否可以獲得媒體時間戳來衡量長度。

讀完之后,它會使用Range bytes=0- (來自另一個套接字號)的另一個請求開始正確地流式傳輸媒體文件。

但是,在任何時候,如果客戶端的用戶執行“跳過”操作,則它發送另一個請求(來自另一個套接字號),其中Range bytes=Z-其中Z是要跳轉到媒體文件中的位置。

我對HTTP的東西不是很好,但據我所知,我需要使用多個線程來處理每個請求/響應,同時允許原始的HttpListener返回監聽。 我做了很多搜索,但找不到一個似乎合適的模型。

編輯:

感謝Rick Strahl對以下示例的感謝,我能夠根據自己的需要進行調整......

使用幾行代碼將Web服務器添加到.NET 2.0應用程序中

如果您需要一個更簡單的替代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
}

您需要使用異步方法才能處理多個請求。 因此,您將使用e BeginGetContextEndGetContext方法。

看看這里

如果您的應用程序在等待客戶端請求時應該阻塞,並且您希望一次只處理一個 * 請求 *,則同步模型是合適的。 使用同步模型,調用GetContext方法,該方法等待客戶端發送請求。 該方法返回一個HttpListenerContext對象,以便在發生時進行處理。

如果您來自未來並嘗試使用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...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM