C# HttpListener 的使用方法


关于监听回调两次的原因,可能是因为重新监听导致的,所以查到微软上面的解析是说

BeginGetContext方法开始异步 (非阻塞) 调用以接收传入的客户端请求。 在调用此方法之前,必须调用 Start 方法,并添加至少一个统一资源标识符 (uri) 前缀,以便通过将 uri 字符串添加到属性返回的来侦听 HttpListenerPrefixCollection Prefixes 。

必须通过调用方法完成异步操作 EndGetContext 。 通常,方法由 callback 委托调用。

操作完成时,此方法不会被阻止。 若要获取传入请求并在操作完成之前一直阻止,请调用 GetContext 方法。

有关使用异步编程模型的详细信息,请参阅 以异步方式调用同步方法

我的猜测是这个

下面是写的一个HttpListener 帮助类

 public class HttpListenerServer : IDisposable
    {
        private readonly HttpListener _listener;
       
        public HttpListenerServer(string[] prefixes)
        { // 检查系统是否支持
            if (!HttpListener.IsSupported)
            {
                throw new ArgumentException("使用 该功能的系统 必须为 Windows XP SP2 或 Server 2003 以上系统!");
            }
            if (prefixes == null || prefixes.Length == 0) 
            {
                throw new ArgumentException("请填写监听地址");
            }
            _listener = new HttpListener();
            foreach (string s in prefixes)
            {
                _listener.Prefixes.Add(s);
            }
            _listener.Start();
            _listener.BeginGetContext(new AsyncCallback(GetContextCallBack), _listener);
        }
        public void Dispose()
        {
            try
            {
                if (_listener != null)
                {
                    _listener.Stop();
                    _listener.Close();
                    _listener.Abort();
                }
                RequestHandlerEven = null;
            }
            catch (Exception)
            {


            }
        }

     

        public delegate object RequestHandler(HttpListenerRequest request);
        public event RequestHandler RequestHandlerEven;
        private void GetContextCallBack(IAsyncResult ar)
        {
            try
            {
                HttpListener httplis = ar.AsyncState as HttpListener;
                if (httplis.IsListening)
                {
                    HttpListenerContext context = httplis.EndGetContext(ar);
                    #region 解析Request请求
                    object resData = null;
                    HttpListenerRequest request = context.Request;
                    if (RequestHandlerEven != null)
                    {
                        resData = RequestHandlerEven(request);
                    }
                    else
                    {
                        resData = new
                        {
                            code = "200",
                            description = "成功",
                            data = "接收数据完成,时间:=" + DateTime.Now
                        };
                    }
                    #endregion 解析Request请求
                    #region 构造Response响应

                    using (HttpListenerResponse response = context.Response)
                    {
                        response.ContentEncoding = Encoding.UTF8;
                        response.ContentType = "application/json;charset=UTF-8";
                        response.AppendHeader("Content-Type", "application/json;charset=UTF-8");
                        try
                        {
                            response.StatusCode = (int)HttpStatusCode.OK;
                            string responseString = JsonConvert.SerializeObject(resData, new JsonSerializerSettings() { StringEscapeHandling = StringEscapeHandling.EscapeNonAscii });
                            using (StreamWriter writer = new StreamWriter(response.OutputStream, Encoding.UTF8))
                            {
                                writer.Write(responseString);
                                writer.Close();
                                response.Close();
                            }
                        }
                        catch (Exception ex)
                        {
                            response.StatusCode = (int)HttpStatusCode.NotFound;
                            response.StatusDescription = "404";
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.WriteLine($"在接收数据时发生错误:{ex.ToString()}");
                            //把服务端错误信息直接返回可能会导致信息不安全,此处仅供参考
                            var returnByteArr = Encoding.UTF8.GetBytes($"在接收数据时发生错误:{ex.ToString()}");//设置客户端返回信息的编码
                            using (var stream = response.OutputStream)
                            {
                                //把处理信息返回到客户端
                                stream.Write(returnByteArr, 0, returnByteArr.Length);
                                stream.Close();
                                response.Close();
                            }
                        }
                    }
                    #endregion 构造Response响应
                    httplis.GetContext();
                    _listener.BeginGetContext(new AsyncCallback(GetContextCallBack), _listener);
                }
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message);
            }
        }


    }
C