2010-11-19 10 views
0

Wir erstellt am Exchange-Webdienst Push-Benachrichtigungen Listener auf der Grundlage der HTTPListener in der EWS-Buch (Code unten). Es lief auf einem Win 2008 Server mit einem Single-Core-Xeon ganz gut. Jetzt haben wir es auf einen Win 2008 R2 Server mit einer Quad Core Opteron CPU verschoben und es stürzt sofort ab, nachdem der Listener mit HTTPListenerExceptions initialisiert wurde. Nun, da sich nichts geändert hat außer dem Server dachte ich, dass es etwas mit Multithreading zu tun haben könnte. Vielleicht kann jemand etwas sagen, danke.HTTPListener stürzt auf Quad-Core-Rechner Win 2008 Server R2

public class PushNotificationClient 
{ 
    private uint portNumber; 
    private NotificationEventsReceived eventHandler; 
    private bool isListening = false; 
    private ManualResetEvent stopEvent = new ManualResetEvent(false); 
    private bool shouldStop = false; 
    private XmlNamespaceManager mgr; 
    private XmlSerializer ser; 

    /// <summary> 
    /// Constructor 
    /// </summary> 
    /// <param name="portNumber">Port number to listen on</param> 
    /// <param name="eventHandler">delegate to call when notifications are 
    /// received</param> 
    /// 
    public PushNotificationClient(
    uint portNumber, 
    NotificationEventsReceived eventHandler) 
    { 
     this.portNumber = portNumber; 
     if (eventHandler == null) 
     { 
      throw new ArgumentNullException("eventHandler"); 
     } 
     this.eventHandler = eventHandler; 
     // namespace manager is used for XPath queries when parsing the request 
     // 
     this.mgr = new XmlNamespaceManager(new NameTable()); 
     this.mgr.AddNamespace("t", 
     "http://schemas.microsoft.com/exchange/services/2006/types"); 
     this.mgr.AddNamespace("m", 
     "http://schemas.microsoft.com/exchange/services/2006/messages"); 
     // XmlSerializer is used to convert SendNotification elements into proxy 
     // class instances 
     // 
     this.ser = new XmlSerializer(typeof(SendNotificationResponseType)); 
    } 

    /// <summary> 
    /// Start Listening 
    /// </summary> 
    public void StartListening() 
    { 
     VerifyNotListening(); 
     this.stopEvent.Reset(); 
     this.shouldStop = false; 
     // Run the listener on a background thread so we are not blocked 
     // 
     ThreadPool.QueueUserWorkItem(new WaitCallback(ListenOnThread)); 
    } 

    /// <summary> 
    /// Stop Listening 
    /// </summary> 
    public void StopListening() 
    { 
     VerifyListening(); 
     // Set the stopEvent. This will cause the worker thread to close our and 
     // dispose of the HttpListener and exit the thread 
     // 
     this.stopEvent.Set(); 
    } 

    /// <summary> 
    /// Thread pool method to start listening on the background thread 
    /// </summary> 
    /// <param name="state">State - ignore</param> 
    /// 
    private void ListenOnThread(object state) 
    { 
     using (HttpListener listener = new HttpListener()) 
     { 
      listener.Prefixes.Add(
       String.Format(
       "http://+:{0}/PushNotificationsClient/", 
       this.portNumber.ToString())); 
      listener.Start(); 
      this.isListening = true; 
      while (!shouldStop) 
      { 
       IAsyncResult asyncResult = listener.BeginGetContext(
       AsyncCallbackMethod, listener); 
       // Wait on either the listener or the stop event 
       // 
       int index = WaitHandle.WaitAny(
       new WaitHandle[] { stopEvent, asyncResult.AsyncWaitHandle }); 
       switch (index) 
       { 
        case 0: 
         // Stop event was triggered. 
         // 
         shouldStop = true; 
         break; 
        case 1: 
         // Notification was received. Just loop around so we can call 
         // BeginGetContext again 
         // 
         break; 
       } 
      } 
      listener.Stop(); 
     } 
     this.isListening = false; 
    } 

    /// <summary> 
    /// Async method called once we receive a request 
    /// </summary> 
    /// <param name="result">Async result containing our HttpListener</param> 
    /// 
    private void AsyncCallbackMethod(IAsyncResult result) 
    { 
     HttpListener listener = result.AsyncState as HttpListener; 
     if (!this.isListening) 
     { 
      // Our callback gets fired when we stop the listener too. If it is not 
      // listening, just return. 
      // 
      return; 
     } 
     HttpListenerContext context = listener.EndGetContext(result); 
     SendNotificationResponseType request; 
     // Now use the XML serializer to turn the XML into a notification 
     // serialization type... 
     // 
     XmlDocument doc = new XmlDocument(); 
     try 
     { 
      doc.LoadXml(
      new StreamReader(
      context.Request.InputStream).ReadToEnd()); 
      // retrieve the first SendNotification element (there should be only one). 
      // 
      XmlNodeList nodes = doc.SelectNodes("//m:SendNotification[1]", this.mgr); 
      if (nodes.Count == 0) 
      { 
       // this wasn't a SendNotification request or it was malformed or 
       // something like that. 
       FailRequest(context); 
       return; 
      } 
      string sendNotification = nodes[0].OuterXml; 
      using (MemoryStream ms = new MemoryStream()) 
      { 
       byte[] bytes = Encoding.UTF8.GetBytes(sendNotification); 
       ms.Write(bytes, 0, bytes.Length); 
       ms.Flush(); 
       ms.Position = 0L; 
       request = (SendNotificationResponseType)this.ser.Deserialize(ms); 
      } 
     } 
     catch (XmlException) 
     { 
      // Failed to deserialize request. 
      // 
      FailRequest(context); 
      return; 
     } 
     // Fire the delegate 
     // 
     NotificationResponse response = eventHandler(
     this, /* sender */ 
     request.ResponseMessages.Items[0] 
     as SendNotificationResponseMessageType); 
     GenerateResponseXML(context, response); 
    } 

    /// <summary> 
    /// Fail the request. Right now we don't differentiate between reasons why it 
    /// failed. 
    /// </summary> 
    /// <param name="context">Request context</param> 
    /// 
    private void FailRequest(HttpListenerContext context) 
    { 
     context.Response.ContentEncoding = Encoding.UTF8; 
     context.Response.ContentType = "text/xml; charset=utf-8"; 
     context.Response.ProtocolVersion = new Version(1, 1, 0, 0); 
     context.Response.StatusCode = 400; 
     string response = "<?xml version=\"1.0\"?>" + 
     "<Error>Bad Request</Error>"; 
     byte[] responseBytes = Encoding.UTF8.GetBytes(response); 
     context.Response.ContentLength64 = responseBytes.Length; 
     context.Response.OutputStream.Write(
     responseBytes, 0, responseBytes.Length); 
     context.Response.OutputStream.Flush(); 
    } 

    /// <summary> 
    /// Generate the response xml 
    /// </summary> 
    /// <param name="context">call context</param> 
    /// <param name="response">The response enum value</param> 
    /// 
    private void GenerateResponseXML(
    HttpListenerContext context, 
    NotificationResponse response) 
    { 
     StringBuilder builder = new StringBuilder(); 
     builder.AppendLine("<?xml version=\"1.0\"?>"); 
     builder.AppendLine("<s:Envelope xmlns:s= " + 
     "\"http://schemas.xmlsoap.org/soap/envelope/\">"); 
     builder.AppendLine("<s:Body>"); 
     builder.AppendLine(" <SendNotificationResult " + 
     "xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\">"); 
     builder.AppendFormat(" <SubscriptionStatus>{0}</SubscriptionStatus>\r\n", 
     response.ToString()); 
     builder.AppendLine(" </SendNotificationResult>"); 
     builder.AppendLine("</s:Body>"); 
     builder.AppendLine("</s:Envelope>"); 
     context.Response.ContentEncoding = Encoding.UTF8; 
     context.Response.ContentType = "text/xml; charset=utf-8"; 
     context.Response.ProtocolVersion = new Version(1, 1, 0, 0); 
     context.Response.StatusCode = 200; 
     byte[] responseBytes = Encoding.UTF8.GetBytes(builder.ToString()); 
     context.Response.ContentLength64 = responseBytes.Length; 
     context.Response.OutputStream.Write(
     responseBytes, 0, responseBytes.Length); 
     context.Response.OutputStream.Flush(); 
    } 

    /// <summary> 
    /// Returns true if the listener is listening 
    /// </summary> 
    public bool IsListening 
    { 
     get 
     { 
      return isListening; 
     } 
    } 
    /// <summary> 
    /// Verifies that the listener isn't listening 
    /// </summary> 
    private void VerifyNotListening() 
    { 
     if (isListening) 
     { 
      throw new PushNotificationStateException("Cannot perform this operation " + 
      "when listening"); 
     } 
    } 

    /// <summary> 
    /// Verifies that the listener is listening 
    /// </summary> 
    private void VerifyListening() 
    { 
     if (!isListening) 
     { 
      throw new PushNotificationStateException("Cannot perform this operation " + 
      "when not listening"); 
     } 
    } 


} 
+0

Sie stellen diese Frage nicht auf die schlaue Art und Weise. Die Ausnahme mag für Sie nichts bedeuten, aber für uns. Nachricht senden + Stapelverfolgung. –

Antwort

2

Es würde helfen, wenn Sie uns bei der Initialisierung gesagt, wo es versagt, aber ich vermute, dass Sie entweder versuchen, einen URI zu registrieren, die Sie nicht mit dem netsh Befehl aktiviert haben, oder du bist versuchen, einen URI zu registrieren, den ein anderer Prozess bereits registriert hat.

Documentation für diese Ausnahme sagt, teilweise:

HttpListenerException wird geworfen werden, wenn die Versuche, HttpListener einen Uniform Resource Identifier registrieren (URI) Präfix, das bereits registriert ist .

Hat ein anderer Prozess bereits registriert http://+:{0}/PushNotificationsClient/? Haben Sie daran gedacht, den Befehl netsh auszuführen, um den URI am richtigen Port zu registrieren und zuhören zu können?

+0

Hallo, nein Ich habe den Befehl netsh nicht ausgeführt, ich habe gerade darüber erfahren, da wir ihn nie auf dem Windows 2008 Server R1-Rechner verwenden mussten. Werde das als erstes am Morgen versuchen, danke! – hoetz

Verwandte Themen