using Ayay.SerilogLogs; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Serilog; namespace SHH.MjpegPlayer { internal class Program { private static ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); static void Main(string[] args) { _sysLog.Information("MjpegPlayer 正在初始化..."); var builder = WebApplication.CreateBuilder(args); // 1. 注册 gRpc 服务 builder.Services.AddGrpc(options => { options.MaxReceiveMessageSize = 10 * 1024 * 1024; // 针对工业视频流,建议放宽至 10MB }); // 2. 注册业务单例(如你之前的 Handler) builder.Services.AddSingleton(); builder.Services.AddSingleton(); var app = builder.Build(); // 3. 映射服务路(将逻辑与端口绑定) app.MapGrpcService(); new Thread(StartServer).Start(); GrpcServerManager.Start(); // 4. 启动监听(代替 Console.ReadLine) // 建议端口与 CameraService 配置的 9002 保持一致 _sysLog.Information("MjpegPlayer gRPC 服务启动于端口 9002"); app.Run("http://0.0.0.0:9002"); } #region StartServer /// /// 开启服务监听 /// static void StartServer() { try { // 加载配置文件 var cfg = Bootstrapper.LoadConfig(); // 检查 IP 与端口 Bootstrapper.ValidateEnvironment(); // 开启 Wcf 服务 StartWcfServer(); _sysLog.Information("WCF 推流接口已就绪, 端口: {Port}", cfg.WcfPushImagePort); // 会话开启 // [修复] 端口循环逻辑:同样改为 <= 以匹配检测逻辑 for (var i = cfg.SvrMjpegPortBegin; i <= cfg.SvrMjpegPortEnd; i++) { MjpegServer.Start(i); } _sysLog.Information("MJPEG 服务池已开启: {Begin} -> {End}", cfg.SvrMjpegPortBegin, cfg.SvrMjpegPortEnd); // 开启 RTMP 服务 RtmpPushServer.Instance.Start(); } catch (Exception ex) { //Logs.LogCritical(ex.Message, ex.StackTrace); // 退出应用 Bootstrapper.ExitApp("应用程序崩溃."); } } #endregion #region StartWcfServer /// /// 开启 Wcf 服务 /// private static void StartWcfServer() { try { var cfg = MjpegStatics.Cfg; Bootstrapper.StartWcfEngine(cfg); } catch (Exception ex) { _sysLog.Fatal(ex, "应用程序崩溃."); // 退出应用 Bootstrapper.ExitApp("应用程序崩溃."); } } #endregion } }