2011-01-26 95 views
4

我使用HttpListener来编写Windows服务来异步处理来自点的请求。HttpListener的C#问题

它工作正常,但有时会遇到需要重新启动服务或服务器进行修复的问题。最初,我宣布听众对象:

public HttpListener PointsListener = new HttpListener(); 

这里是我开始听的方法的代码。我是从OnStart方法的服务调用它:

public string ListenerStart() 
    { 
     try 
     { 
      if (!PointsListener.IsListening) 
      { 
       PointsListener.Prefixes.Add(String.Concat("http://*:", points_port, "/")); 
       PointsListener.Start(); 
       PointsListener.BeginGetContext(PointProcessRequest, PointsListener); 

       LogWriter("Http listener activated on port " + points_port); 
       return "Listener started"; 
      } 
      else 
      { 
       return "Listener is already started!"; 
      } 

     } 
     catch (Exception err) 
     { 
      LogWriter("Error in LIstenerStart \r\n" + err.ToString()); 
      return ("Error: " + err.Message); 
     } 
    } 

下面是其处理请求的方法:

private void PointProcessRequest(IAsyncResult result) 
    { 
     HttpListener listener = (HttpListener)result.AsyncState; 
     HttpListenerContext context = listener.EndGetContext(result); 
     HttpListenerRequest request = context.Request; 
     HttpListenerResponse response = context.Response; 
     response.KeepAlive = false; 
     System.IO.Stream output = response.OutputStream; 

     try 
     { 
      //declaring a variable for responce 
      string responseString = "<html>My Response: request is not allowed by server protocol</html>"; 


      // Commands and actions to set responceString 

      byte[] buffer = Encoding.UTF8.GetBytes(responseString); 
      response.ContentLength64 = buffer.Length; 
      output.Write(buffer, 0, buffer.Length); 
     } 
     catch (Exception err) 
     { 
      LogWriter("Error in PointProcessRequest: \r\n" + err.ToString()); 
     } 
     finally 
     { 
      try 
      { 
       output.Flush(); 
       output.Close(); 
       response.Close(); 
      } 
      catch (Exception err) 
      { 
       LogWriter("Error in PointProcessRequest CLOSING OUTPUT STREAM: \r\n" + err.ToString()); 
      } 
      finally 
      { 
       PointsListener.BeginGetContext(PointProcessRequest, PointsListener); 
      } 
     } 
    } 

它运作良好一些的时间,但会出现在下面的错误日志:

Error in PointProcessRequest: 
System.Net.HttpListenerException: The specified network name is no longer available 
    в System.Net.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 size) 
    в ARK_Dealer.ark.PointProcessRequest(IAsyncResult result) 

[26.01.2011 9:00:54] Error in PointProcessRequest CLOSING OUTPUT STREAM: 
System.InvalidOperationException: Cannot close stream until all bytes are written. 
    в System.Net.HttpResponseStream.Dispose(Boolean disposing) 
    в System.IO.Stream.Close() 
    в ARK_Dealer.ark.PointProcessRequest(IAsyncResult result) 

我认为当某个点向服务器发送请求但在接收应答失去连接之前,会出现此问题。

如何防止异常被抛出?将响应对象自动处理好吗?我该如何解决这个问题?

回答

2

有关于此的related question

你在做什么都很好,因为除了关闭连接或断开连接的另一端之外,没有别的办法可以做到。您可能想要捕获确切的异常并呼叫output.Dispose()和其他清理,或者只是让终结器处理发布,如果它不经常发生。

+0

我稍微纠正了PointProcess方法,并插入在你写的Dispose那里。让我监控系统几天,看看它会生效还是不生效。非常感谢你! – Khisrav 2011-01-26 08:24:44

+0

再次问候!请注释我的最终决定,当写入响应输出流我使用以下代码: using(System.IO.Stream output = response.OutputStream) { output.Write(buffer,0,buffer.Length); } 如果发生异常,它将被写入日志,并且如果代码运行,对象输出将自动处理。我对么?谢谢! – Khisrav 2011-01-26 10:23:14

+0

你还在关闭`response`对象吗? – Amir 2011-01-26 16:16:40

2

最近我有同样的问题,并通过在一个try/catch包裹输出解决它:

try 
{ 
    byte[] buffer = Encoding.UTF8.GetBytes(responseString); 
    response.ContentLength64 = buffer.Length; 
    output.Write(buffer, 0, buffer.Length); 
} 
catch (HttpListenerException) 
{ 
    // Handle error caused by connection being lost 
} 
2

问题解决了!我刚刚删除了这个:

finally 
{ 
PointsListener.BeginGetContext(PointProcessRequest, PointsListener); 
} 

并且在PointProcessRequest方法的开头插入了这个命令!

IAsyncResult _result = listener.BeginGetContext(new AsyncCallback(PointProcessRequest), listener); 

问题在100%解决!

4

我在生产中使用了一个HttpListener,并且我找到了解决这个问题的最好方法,无需添加一大堆try/catch块,它们无法传递手头代码的逻辑;是很简单地设置Listener.IgnoreWriteExceptions = true;,并没有更多的写例外!