异步的HttpListener已每个请求收到两次 [英] Asynchronous HttpListener has each request is received twice

查看:391
本文介绍了异步的HttpListener已每个请求收到两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经实现了在C#中的异步HTTP侦听器。

我跟着提供的教程这里由微软

和发现另一个教程,我愣神不书签,现在找不到了。这意味着我有,我就不会写这样一些code自己,而是提供有意义的解释,所以我接着说。

现在我面临着两个问题:

首先,我已经和一次第二,Listener.Stop()每个请求后,重新启动监听器,然后调用StartListening方法,当我这样做,我收到的每个请求的两倍。 该请求中网被发送两次,但我得到了两遍。 但是,它没有得到的时候我暂停线程我听的约2秒钟收到两次。

我很抱歉,如果我在我的解释很含糊,但让我我的问题的理解,我不知道是什么原因造成的。 由于回调方法是大多数的事情发生,我只是张贴,请告诉我,如果你需要更多的code。 任何帮助将非常乐意AP preciated,因为我真的很坚持这一点。

 公共无效ListenAsynchronously()
    {

        如果(监听器prefixes.Count == 0)的foreach(字符串s $ p中$ pfixes)监听器prefixes.Add(S)。

        尝试
        {
            listener.Start();
        }
        赶上(例外五)
        {
            Logging.logException(E);
        }

        System.Threading.ThreadPool.QueueUserWorkItem(新System.Threading.WaitCallback(听));
    }


    私人无效听(对象状态)
    {
        而(listener.IsListening)
        {
            listener.BeginGetContext(新的AsyncCallback(ListenerCallback),监听器);
            listenForNextRequest.WaitOne();
        }
    }
     私人无效ListenerCallback(IAsyncResult的AR)
    {

        的HttpListener的HttpListener = ar.AsyncState为System.Net.HttpListener;
        System.Net.HttpListenerContext上下文= NULL;

        INT requestNumber = System.Threading.Interlocked.Increment(REF requestCounter);

        如果(的HttpListener == NULL)回报;

        尝试
        {
            上下文= httplistener.EndGetContext(AR);
        }
        赶上(例外前)
        {
            返回;
        }
        最后
        {
            listenForNextRequest.Set();
        }

        如果(背景== NULL)回报;


        System.Net.HttpListenerRequest请求= context.Request;

        如果(request.HasEntityBody)
        {
            使用(就是System.IO.StreamReader SR =新就是System.IO.StreamReader(request.InputStream,request.ContentEncoding))
            {
                字符串=的RequestData sr.ReadToEnd();

                //东西我做的请求,发生在这里

            }
        }


        尝试
        {
            使用(System.Net.HttpListenerResponse响应= context.Response)
            {
                //响应的东西在这里发生

                }

                byte []的缓冲区= System.Text.Encoding.UTF8.GetBytes(responseString);
                response.ContentLength64 = buffer.LongLength;
                response.OutputStream.Write(缓冲液,0,buffer.Length);
                response.Close();


                的stopListening();
                //如果我不设置线程睡在这里,我收到了双倍的请求
                System.Threading.Thread.Sleep(2500);

                ListenAsynchronously();


            }
        }
        赶上(例外五)
        {
        }

    }
 

解决方案

我不知道你为什么叫的stopListening() ListenAsynchronously( ) ListenerCallback()方法。该收听()方法正在运行一个线程,并会继续得到各下一传入的请求。如果我写这个,我也不会用的HttpListener的实例变量。在ListenAsynchronously方法创建一个新的,并通过它在你的状态对象,例如,

 公共类HttpListenerCallbackState
{
    私人只读的HttpListener _listener;
    私人只读的AutoResetEvent _listenForNextRequest;

    公共HttpListenerCallbackState(的HttpListener监听器)
    {
        如果(听众== NULL)抛出新ArgumentNullException(监听器​​);
        _listener =侦听器;
        _listenForNextRequest =新的AutoResetEvent(假);
    }

    公众的HttpListener监听{{返回_listener; }}
    公众的AutoResetEvent ListenForNextRequest {{返回_listenForNextRequest; }}
}

公共类的Htt prequestHandler
{
    私人诠释requestCounter = 0;
    私人ManualResetEvent的stopEvent =新的ManualResetEvent(假);

    公共无效ListenAsynchronously(IEnumerable的<字符串> prefixes)
    {
        的HttpListener监听器=新的HttpListener();

        的foreach(字符串s $ p中$ pfixes)
        {
            。监听器prefixes.Add(S);
        }

        listener.Start();
        HttpListenerCallbackState状态=新HttpListenerCallbackState(听众);
        ThreadPool.QueueUserWorkItem(听,状态);
    }

    公共无效的stopListening()
    {
        stopEvent.Set();
    }


    私人无效听(对象状态)
    {
        HttpListenerCallbackState callbackState =(HttpListenerCallbackState)状态;

        而(callbackState.Listener.IsListening)
        {
            callbackState.Listener.BeginGetContext(新的AsyncCallback(ListenerCallback),callbackState);
            INT N = WaitHandle.WaitAny(新的WaitHandle [] {callbackState.ListenForNextRequest,stopEvent});

            如果(正== 1)
            {
                // stopEvent是信号
                callbackState.Listener.Stop();
                打破;
            }
        }
    }

    私人无效ListenerCallback(IAsyncResult的AR)
    {
        HttpListenerCallbackState callbackState =(HttpListenerCallbackState)ar.AsyncState;
        HttpListenerContext上下文= NULL;

        INT requestNumber = Interlocked.Increment(REF requestCounter);

        尝试
        {
            上下文= callbackState.Listener.EndGetContext(AR);
        }
        赶上(例外前)
        {
            返回;
        }
        最后
        {
            callbackState.ListenForNextRequest.Set();
        }

        如果(背景== NULL)回报;


        HttpListenerRequest请求= context.Request;

        如果(request.HasEntityBody)
        {
            使用(就是System.IO.StreamReader SR =新就是System.IO.StreamReader(request.InputStream,request.ContentEncoding))
            {
                字符串=的RequestData sr.ReadToEnd();

                //东西我做的请求,发生在这里
            }
        }


        尝试
        {
            使用(HttpListenerResponse响应= context.Response)
            {
                //响应的东西在这里发生
                字符串responseString =确定;

                byte []的缓冲区= Encoding.UTF8.GetBytes(responseString);
                response.ContentLength64 = buffer.LongLength;
                response.OutputStream.Write(缓冲液,0,buffer.Length);
                response.Close();
            }
        }
        赶上(例外五)
        {
        }
    }
}
 

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)
        {
        }
    }
}

这篇关于异步的HttpListener已每个请求收到两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆