I have implemented an asynchronous http listener in c#.
I followed the tutorial provided here by Microsoft
and found another tutorial which i stupidly not bookmarked and now can't find again. Meaning that I have some code that I would not have written that way myself but the explanations provided made sense so I followed that.
Now I am facing two problems:
First, I have to restart the listener after each request with Listener.Stop() and then call the StartListening method and again and second, when I do this, I receive each request twice. The request does net get sent twice, but I receive it twice. It does not however get received twice when I pause the Thread I am listening on for about 2 seconds.
I am sorry if I am quite vague in my explanations, but so is my understanding of my problem, I have no idea what is causing it. Since the callback method is where most of the stuff happens, I will just post it, please tell me if you need any more code. Any help will be gladly appreciated, since I am really stuck on this one.
public void ListenAsynchronously()
    {
        if (listener.Prefixes.Count == 0) foreach (string s in prefixes) listener.Prefixes.Add(s);
        try
        {
            listener.Start();
        }
        catch (Exception e)
        {
            Logging.logException(e); 
        }
        System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(Listen));
    }
    private void Listen(object state)
    {
        while (listener.IsListening)
        {
            listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
            listenForNextRequest.WaitOne();
        }
    }
     private void ListenerCallback(IAsyncResult ar)
    {
        HttpListener httplistener = ar.AsyncState as System.Net.HttpListener;
        System.Net.HttpListenerContext context = null;
        int requestNumber = System.Threading.Interlocked.Increment(ref requestCounter);
        if (httplistener == null) return;
        try
        {
            context = httplistener.EndGetContext(ar);
        }
        catch(Exception ex)
        {
            return;
        }
        finally
        {
            listenForNextRequest.Set();
        }
        if (context == null) return;
        System.Net.HttpListenerRequest request = context.Request;
        if (request.HasEntityBody)
        {
            using (System.IO.StreamReader sr = new System.IO.StreamReader(request.InputStream, request.ContentEncoding))
            {
                string requestData = sr.ReadToEnd();
                //Stuff I do with the request happens here
            }
        }
        try
        {
            using (System.Net.HttpListenerResponse response = context.Response)
            {
                //response stuff happens here
                }
                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
                response.ContentLength64 = buffer.LongLength;
                response.OutputStream.Write(buffer, 0, buffer.Length);
                response.Close();
                StopListening();
                //If I dont set the thread to sleep here, I receive the double requests
                System.Threading.Thread.Sleep(2500);
                ListenAsynchronously(); 
            }
        }
        catch (Exception e)
        {
        }
    }
                I am not sure why you are calling StopListening() and ListenAsynchronously() in your ListenerCallback() method.  The Listen() method is being run in a thread and will continue to get each next incoming request. If I was writing this, I would not be using a instance variable of HttpListener.  Create a new one in your ListenAsynchronously method and pass it in your state object, for example,
public class HttpListenerCallbackState
{
    private readonly HttpListener _listener;
    private readonly AutoResetEvent _listenForNextRequest;
    public HttpListenerCallbackState(HttpListener listener)
    {
        if (listener == null) throw new ArgumentNullException("listener");
        _listener = listener;
        _listenForNextRequest = new AutoResetEvent(false);
    }
    public HttpListener Listener { get { return _listener; } }
    public AutoResetEvent ListenForNextRequest { get { return _listenForNextRequest; } }
}
public class HttpRequestHandler
{
    private int requestCounter = 0;
    private ManualResetEvent stopEvent = new ManualResetEvent(false);
    public void ListenAsynchronously(IEnumerable<string> prefixes)
    {
        HttpListener listener = new HttpListener();
        foreach (string s in prefixes)
        {
            listener.Prefixes.Add(s);
        }
        listener.Start();
        HttpListenerCallbackState state = new HttpListenerCallbackState(listener);
        ThreadPool.QueueUserWorkItem(Listen, state);
    }
    public void StopListening()
    {
        stopEvent.Set();
    }
    private void Listen(object state)
    {
        HttpListenerCallbackState callbackState = (HttpListenerCallbackState)state;
        while (callbackState.Listener.IsListening)
        {
            callbackState.Listener.BeginGetContext(new AsyncCallback(ListenerCallback), callbackState);
            int n = WaitHandle.WaitAny(new WaitHandle[] { callbackState.ListenForNextRequest, stopEvent});
            if (n == 1)
            {
                // stopEvent was signalled 
                callbackState.Listener.Stop();
                break;
            }
        }
    }
    private void ListenerCallback(IAsyncResult ar)
    {
        HttpListenerCallbackState callbackState = (HttpListenerCallbackState)ar.AsyncState;
        HttpListenerContext context = null;
        int requestNumber = Interlocked.Increment(ref requestCounter);
        try
        {
            context = callbackState.Listener.EndGetContext(ar);
        }
        catch (Exception ex)
        {
            return;
        }
        finally
        {
            callbackState.ListenForNextRequest.Set();
        }
        if (context == null) return;
        HttpListenerRequest request = context.Request;
        if (request.HasEntityBody)
        {
            using (System.IO.StreamReader sr = new System.IO.StreamReader(request.InputStream, request.ContentEncoding))
            {
                string requestData = sr.ReadToEnd();
                //Stuff I do with the request happens here  
            }
        }
        try
        {
            using (HttpListenerResponse response = context.Response)
            {
                //response stuff happens here  
                string responseString = "Ok";
                byte[] buffer = Encoding.UTF8.GetBytes(responseString);
                response.ContentLength64 = buffer.LongLength;
                response.OutputStream.Write(buffer, 0, buffer.Length);
                response.Close();
            }
        }
        catch (Exception e)
        {
        }
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With