首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >异步HttpListener使每个请求都收到两次

异步HttpListener使每个请求都收到两次
EN

Stack Overflow用户
提问于 2011-05-05 16:57:40
回答 1查看 8.4K关注 0票数 5

我已经在c#中实现了一个异步http侦听器。

我遵循了here by Microsoft提供的教程

我发现了另一个教程,我愚蠢地没有加书签,现在也找不到了。这意味着我有一些我自己不会用这种方式编写的代码,但是提供的解释是有意义的,所以我遵循了它。

我现在面对两个问题:

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

如果我的解释很含糊,我很抱歉,但我对我的问题的理解也是如此,我不知道是什么导致了它。因为回调方法是大多数事情发生的地方,所以我只发布它,如果你需要更多的代码,请告诉我。任何帮助都将非常感谢,因为我真的被困在这个问题上了。

代码语言:javascript
运行
复制
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)
        {
        }

    }
EN

Stack Overflow用户

回答已采纳

发布于 2012-01-28 00:13:09

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

代码语言:javascript
运行
复制
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)
        {
        }
    }
}
票数 6
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5895063

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档