【问题标题】:How do I make System.Net.HttpListener long running, or is there a better way?如何使 System.Net.HttpListener 长时间运行,还是有更好的方法?
【发布时间】:2021-12-20 16:18:26
【问题描述】:

应用程序

我正在从事一个 IIoT 项目。我需要能够在一台其 HMI 在 Win7 上运行的设备上接收简单的消息(json 有效负载)。在某些情况下,我们为此使用 3rd 方 MQTT,但对于这种情况,我正在研究 HTTP,特别是 C#(.NET Framework 4.0)中的小型 http 服务器。不需要前端,只需一个带有单个端点的 api。

接近

我找到了System.Net.HttpListener,并让它在控制台应用程序中做我想做的事情以进行初始测试。问题是我正在使用阻塞主线程的GetContext 方法。直觉上,这不是我想要的,但我不知道更合理的方法。我看到有一个内置的异步方法HttpListener.BeginGetContext,但这足以满足我的要求吗?最终希望使用 TopShelf NuGet 包将其包装到服务中。

不是在寻找代码完整的解决方案,而是在寻找合适的概念方法。

【问题讨论】:

    标签: c# httplistener long-running-processes


    【解决方案1】:

    您可以使用 Microsoft.Owin 包在控制台应用程序中托管 http 控制器

    想法是在这种情况下您不需要安装 IIS。 如果需要,您可以将应用程序托管为 Windows 服务(使用 TopShelf)。

    但是,您正在使 ASP 控制器正常工作,不应该再为 HttpListeners 烦恼。

    有很多可用的操作指南,例如here

    简而言之,您必须这样做

    添加Microsoft.AspNet.WebApi.OwinSelfHost

    在代码中配置Owin就像

    public class SelfHostStart 
    {
        private readonly WebSettings config;
    
        public SelfHostStart(WebSettings config)
        {
            this.config = config;
        }
    
        void Start<T>(string hostAddress, string message)
        {
            if (string.IsNullOrEmpty(hostAddress))
                throw new ArgumentException("hostAddress", $"no value to start host {message}");
    
            var oh = new OwinHost();
            server = oh.Start<T>(hostAddress, message);
        }
    
    
        public void Start()
        {
            if (config?.Enabled == true)
            {
                Start<Startup>(config.HostAddress, "webServer");
            }
        }
    }              
    
        public class WebSettings 
        {
            public bool Enabled { get; set; }
    
            public string HostAddress { get; set; }
        }
    

    然后您可以创建Startup.cs 来配置 http 托管,如下所示:

    public class Startup
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            HttpConfiguration config = GetHttpConfig(appBuilder);
    
            ConfigureWebApi(appBuilder, config);
    DEBUG
            config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.LocalOnly;
    if
            appBuilder.UseCors(CorsOptions.AllowAll);
            appBuilder.UseWebApi(config);
        }
    
        public HttpConfiguration GetHttpConfig(IAppBuilder appBuilder)
        {
            var config = new HttpConfiguration();
    // you may override some default behavior here
            //config.Services.Replace(typeof(IHttpControllerActivator), new UnityControllerActivator());
            //config.Services.Add(typeof(System.Web.Http.ExceptionHandling.IExceptionLogger), new ExceptionLog(appBuilder.CreateLogger<ExceptionLog>()));
            //config.Services.Replace(typeof(System.Web.Http.ExceptionHandling.IExceptionHandler), new CustomExceptionHandler()); // to make ExceptionHandler works 
    
            //config.MessageHandlers.Add(new LoggingHandler(appBuilder.CreateLogger("rest")));
    
            return config;
        }
    
        public void ConfigureWebApi(IAppBuilder app, HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
               name: "DefaultApi",
               routeTemplate: "api/{controller}/{id}",
               defaults: new { id = RouteParameter.Optional }
           );
    
            config.EnsureInitialized();
        }
    }
    

    和控制器(具有可用于服务客户端的方法的类):

    [AllowAnonymous]
    public class StatusController : ApiController
    {
        public StatusController()
        {
        }
    
        [Route("status")]
        public StatusDto Get()
        {
            var res = new StatusDto
            {
                DbVersion = "123",
                LocalCurrency = "USD",
                SwiftCode = "12345", // just sample
            };
    
            return res;
        }
    }
    
    public class StatusDto
    {
        public string DbVersion { get; set; }
        public string LocalCurrency { get; set; }
        public string SwiftCode { get; set; }
    }
    
    

    并在您的控制台中启动 http 服务器

    var config = new WebSettings() { HostAddress = "http://localhost:8080" };
    var start = new SelfHostStart(config);
    start.Start();
    

    您应该使用netsh http add urlacl 命令为您的控制台提供侦听 http url 的权限,例如

    netsh http 添加 urlacl url=http://+:8080/ user=everyone

    然后你可以浏览 http://localhost:8080/status 并且应该从 http 控制台服务器获取报告。

    您可以通过使用方法创建新控制器来扩展您的服务

    【讨论】:

      猜你喜欢
      • 2020-02-09
      • 2023-03-09
      • 2012-06-05
      • 1970-01-01
      • 2013-07-12
      • 1970-01-01
      • 2018-06-03
      • 1970-01-01
      • 2011-07-03
      相关资源
      最近更新 更多