2011-05-05 81 views
5

我已經在c#中實現了一個異步http偵聽器。異步HttpListener有兩次收到每個請求

我跟着教程提供here by Microsoft

,發現我愣神不書籤另一個教程,現在無法再次找到。這意味着我有一些我自己不會這樣寫的代碼,但是提供的解釋是有道理的,所以我遵循了它。

現在我面臨兩個問題:

首先,我有Listener.Stop()每個請求後,重新啓動監聽器,然後,再而第二調用StartListening方法,我這樣做的時候,我收到每次請求兩次。 請求確實發送了兩次,但我收到了兩次。 但是,當我暫停我正在監聽約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) 
     { 
     } 

    } 
+0

不知道什麼調用此回調,WaitHandle的listenForNextRequest是如何使用和ListenAsynchronously做什麼方法,這是一個有點猜謎遊戲。 – spender 2011-05-05 09:06:58

+0

對不起,我添加了代碼 – Daniel 2011-05-05 10:01:56

+0

,你應該打印出來給控制檯(或者如果你願意,可以登錄文件)一些有用的調試信息並在這裏發佈。請指定您用於運行此代碼及其版本的操作系統。通過這種方式將更加簡單,試圖幫助你...關心, Giacomo – gsscoder 2011-11-10 06:39:30

回答

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

我用這個作爲服務簡單網頁的基礎.Net 2.0應用程序,我對它的工作效果印象非常深刻。在我的筆記本電腦上,我能夠每秒向一個簡單的單線程加載測試腳本提供約130-200個請求,並且每秒向該測試腳本的5個實例每秒提供約20個請求。在這些測試中,服務器代碼使用了大約12%的CPU。 – 2013-08-15 21:10:50