首页 文章

异步HttpListener每次接收两次请求

提问于
浏览
5

我在c#中实现了一个异步http监听器 .

我按照提供的教程here by Microsoft

并发现另一个教程,我愚蠢地没有书签,现在再也找不到了 . 这意味着我有一些代码,我自己不会这样写,但所提供的解释是有道理的,所以我遵循了这一点 .

现在我面临两个问题:

首先,我必须在使用Listener.Stop()的每个请求之后重新启动侦听器,然后再次调用StartListening方法,其次,当我这样做时,我会收到两次请求 . 请求发送net get两次,但我收到两次 . 然而,当我暂停我正在收听的线程大约2秒时,它不会被接收两次 .

我很抱歉,如果我的解释很模糊,但我对我的问题的理解也是如此,我不知道是什么导致了它 . 由于回调方法是大多数事情发生的地方,我将发布它,请告诉我你是否需要更多的代码 . 任何帮助都将很高兴,因为我真的被困在这一个 .

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

    }

1 回答

  • 6

    我不知道你为什么在 ListenerCallback() 方法中调用 StopListening()ListenAsynchronously() . Listen() 方法正在一个线程中运行,并将继续获取每个下一个传入请求 . 如果我写这篇文章,我就不会使用HttpListener的实例变量 . 在ListenAsynchronously方法中创建一个新方法并将其传递给状态对象,例如,

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

相关问题