Подтвердить что ты не робот

Обработка нескольких запросов с помощью С# HttpListener

У меня есть служба Windows.NET, которая порождает поток, который в основном просто действует как 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=X-Y. В этом случае Y - длина содержимого, возвращаемая в первом ответе, и X на 250000 байт меньше, чем это (обнаружено с использованием IIS в качестве теста). На этом этапе он получает последний "кусок", чтобы узнать, может ли он получить временную метку носителя для измерения длины.

Прочитав это, он делает еще один запрос с Range bytes=0- (из другого номера сокета), чтобы начать корректную передачу медиафайла.

В любом случае, если пользователь клиента выполняет операцию "skip", он затем отправляет другой запрос (из еще одного номера сокета) с помощью Range bytes=Z-, где Z - это позиция для перехода в медиафайл.

Я не очень хорошо разбираюсь в HTTP-материалах, но насколько я могу судить, мне нужно использовать несколько потоков для обработки каждого запроса/ответа, позволяя исходному HttpListener вернуться к прослушиванию. Я много раз искал, но не могу найти подходящую модель.

EDIT:

Благодарность и благодарность Рику Страллу за следующий пример, который я смог адаптировать в соответствии с моими потребностями...

Добавьте веб-сервер в свое приложение .NET 2.0 с несколькими строками кода

4b9b3361

Ответ 1

Если вам нужна более простая альтернатива 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
}

Ответ 2

Вам нужно использовать метод async для обработки нескольких запросов. Поэтому вы должны использовать методы e BeginGetContext и EndGetContext.

Посмотрите здесь.

Синхронная модель подходит, если ваше приложение должно блокировать в ожидании запроса клиента, и если вы хотите обработать только один* запрос за раз *. Используя синхронную модель, вызовите GetContext метод, который ожидает, что клиент отправит запрос. Метод возвращает объект HttpListenerContext для обработки, если он возникает.

Ответ 3

Если вы здесь из будущего и пытаетесь обрабатывать несколько одновременных запросов одним потоком, используя 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...
}