HttpListener的C#问题

Khi*_*rav 5 c#

我编写了一个Windows服务,使用一个HttpListener异步处理来自点的请求.

它运行正常,但有时会遇到需要重新启动服务或服务器才能修复的问题.最初我用以下方法声明了侦听器对象:

public HttpListener PointsListener = new HttpListener();
Run Code Online (Sandbox Code Playgroud)

这是我开始收听的方法的代码.我是从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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

以下是处理请求的方法:

    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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

它在某些时候运行良好,但日志中出现以下错误:

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)
Run Code Online (Sandbox Code Playgroud)

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

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

Jos*_*osh 5

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

  • 在很多层面都是错的!如果你不断地写入流,而另一侧关闭出于某种原因,连接,你就不会例外扔在write()调用,因为你忽略了写异常,您的应用程序将继续写入流,它看起来像是开放的...... (5认同)
  • IgnoreWriteExceptions是要走的路.我不同意Cipi和他的"边缘案例",它甚至对HTTP协议都没有意义. (2认同)
  • @Lubos,Cipi的回应非常有意义.如果您的请求是下载大文件怎么办?如果忽略异常,即使字节永远不会到达客户端,您仍将继续读取文件. (2认同)

Ami*_*mir 2

有一个与此相关的问题。

您正在做的事情很好,因为对于另一方关闭连接或连接被丢弃没有什么可以做的。您可能想要捕获确切的异常并调用output.Dispose()和其他清理,或者只是让终结器处理发布(如果它不经常发生)。