C # и запуск HttpListener в фоновом режиме - PullRequest
1 голос
/ 23 февраля 2012

Я создал простой HttpListener, который прослушивает порт 9090 и в зависимости от URL-адреса запроса записывает некоторую информацию в консоль.

Но я застрял :( Я думал о многопоточности, системе, основанной на событиях, ноЯ ничего не могу с этим поделать.

Вот код моего слушателя, который я запустил как отдельное консольное приложение:

string urlTemplate = String.Format("/prefix/{0}/suffix", id);
string prefix = String.Format("http://localhost:9090/");

HttpListener listener = new HttpListener();
listener.Prefixes.Add(prefix);

listener.Start();

Console.WriteLine("Listening to {0}...", prefix);

while (true)
{
    HttpListenerContext context = listener.GetContext();
    HttpListenerRequest request = context.Request;

    //Response object
    HttpListenerResponse response = context.Response;

    //Construct response
    if (request.RawUrl.Contains(urlTemplate) && request.HttpMethod == "POST")
    {
         string requestBody;
         Stream iStream = request.InputStream;
         Encoding encoding = request.ContentEncoding;
         StreamReader reader = new StreamReader(iStream, encoding);
         requestBody = reader.ReadToEnd();

         Console.WriteLine("POST request on {0} with body = [{1}]", request.RawUrl, requestBody);

         response.StatusCode = (int)HttpStatusCode.OK;

         //Return a response
         using (Stream stream = response.OutputStream) { }
     }
     else
     {
         response.StatusCode = (int)HttpStatusCode.BadRequest;
         Console.WriteLine("Invalid HTTP request: [{0}] {1}", request.HttpMethod, request.Url);
         using (Stream stream = response.OutputStream) { }
     }
}

Я решил использовать его как утилитудля модульных тестов (возможно, где-то еще). Поэтому при запуске теста мне нужно настроить прослушиватель, запустить его, затем сделать несколько запросов и получить информацию (которую слушатель ранее записал в консоль), и в конце теста остановить слушателя.

Моя основная идея заключалась в инкапсуляции этого слушателя в отдельный класс MyHttpListener, который имеет методы: StartListener(), StopListener().

Но когда я вызываю StartListener(), мой тест зависает, потому чтобесконечного цикла while. Я пытался создать отдельный фоновый поток или систему, основанную на событиях, но мой недостаток опыта с ними мешает мне это сделать. Я уже потратил много времени, пытаясь найтирешение, но все ни за что.

Надеюсь, вы можете помочь мне найти решение для такой тривиальной задачи.

Заранее спасибо.

1 Ответ

1 голос
/ 24 февраля 2012

Один из вариантов респондента (кажется, он удалил свой пост) выглядел хорошо, но у меня это не сработало. Я пытался все исправить, чтобы он начал работать, но в конце этот вариант дал мне представление о том, как решить проблему - с многопоточностью и событиями

Вот что у меня сейчас и работает:

public delegate void HttpListenerRequestHandler(object sender, HttpListenerEventArgs e);
public event HttpListenerRequestHandler OnCorrectRequest;

...

if(OnCorrectRequest != null)
    OnCorrectRequest(this, new HttpListenerEventArgs(response));
lock (threadLock)
{
    Console.WriteLine("POST request on {0} with body = [{1}]", request.RawUrl, requestBody);
}

...

public class HttpListenerEventArgs : EventArgs
{
    public readonly HttpListenerResponse response;
    public HttpListenerEventArgs(HttpListenerResponse httpResponse)
    {
        response = httpResponse;
    }
}

Чтобы получить подробные ответы от HttpListener в основном потоке, я использую следующее:

private HttpListenerResponse response;

public void HttpCallbackRequestCorrect(object sender, HttpListenerEventArgs e)
{
    response = e.response;
    Console.WriteLine("{0} sent: {1}", sender, e.response.StatusCode);
}

К сожалению, у меня есть следующее исключение, которое я не знаю, как обработать:

System.Net.HttpListenerException: операция ввода-вывода была прервана из-за выхода из потока или запроса приложения в System.Net.HttpListener.GetContext ()

...