/// <summary> /// http服务启动,初始化代码写在这里 /// </summary> /// <param name="ctsHttp"></param> /// <param name="WebManagementPort"></param> /// <returns></returns> public async Task StartHttpService(CancellationTokenSource ctsHttp, int WebManagementPort) { try { HttpListener listener = new HttpListener(); //缓存所有文件 var dir = new DirectoryInfo(BASE_FILE_PATH); var files = dir.GetFiles("*.*"); foreach (var file in files) { using (var fs = file.OpenRead()) { var mms = new MemoryStream(); fs.CopyTo(mms); FilesCache.Add(file.Name, mms); } } Logger.Debug($"{files.Length} files cached."); listener.Prefixes.Add($"http://+:{WebManagementPort}/"); Logger.Debug("Listening HTTP request on port " + WebManagementPort.ToString() + "..."); await AcceptHttpRequest(listener, ctsHttp); } catch (HttpListenerException ex) { Logger.Debug("Please run this program in administrator mode." + ex); Logger.Error(ex.ToString(), ex); } catch (Exception ex) { Logger.Debug(ex); Logger.Error(ex.ToString(), ex); } Logger.Debug("Http服务结束。"); }
private async Task ProcessHeartbeatsCheck(int interval, CancellationTokenSource cts) { try { while (!cts.Token.IsCancellationRequested) { //Server.Logger.Debug("开始心跳检测"); var outTimeClients = ServerContext.Clients.Where( (cli) => DateTimeHelper.TimeRange(cli.LastUpdateTime, DateTime.Now) > interval).ToList(); foreach (var client in outTimeClients) { ServerContext.CloseAllSourceByClient(client.ClientID); } //Server.Logger.Debug("结束心跳检测"); await Task.Delay(interval); } } catch (Exception ex) { Logger.Error(ex.Message, ex); } finally { Logger.Debug("fatal error:心跳检测处理异常终止。"); //TODO 重新开始 } }
private async Task ProcessHttpRequestAsync(HttpListenerContext context) { try { var request = context.Request; var response = context.Response; response.ContentEncoding = Encoding.UTF8; response.ContentType = "text/html;charset=utf-8"; //TODO ***通过request来的值进行接口调用 //getJson var json = GetClientsInfoJson(); await response.OutputStream.WriteAsync(HtmlUtil.GetContent(json.ToString())); //await response.OutputStream.WriteAsync(HtmlUtil.GetContent(request.RawUrl)); response.OutputStream.Close(); } catch (Exception e) { Logger.Error(e.Message, e); throw; } }
/// <summary> /// 重要:连接服务端 /// </summary> /// <returns></returns> public async Task ConnectToProvider() { var appIdIpPortConfig = ClientConfig.Clients; ConnnectionManager = ServerConnnectionManager.Create(); ConnnectionManager.ClientGroupConnected += ServerConnnectionManager_ClientGroupConnected; var clientModel = await ConnnectionManager.InitConfig(); int counter = 0; //appid为0时说明没有分配appid,所以需要分配一个 foreach (var app in appIdIpPortConfig) { if (app.AppId == 0) { app.AppId = clientModel.AppList[counter].AppId; counter++; } } Logger.Debug("****************port list*************"); foreach (var ap in clientModel.AppList) { var cApp = appIdIpPortConfig.First(obj => obj.AppId == ap.AppId); Logger.Debug(ap.AppId.ToString() + ": " + ClientConfig.ProviderAddress + ":" + ap.Port.ToString() + "=>" + cApp.IP + ":" + cApp.TargetServicePort); } Logger.Debug("**************************************"); Task pollingTask = ConnnectionManager.PollingToProvider(); try { await pollingTask; } catch (Exception ex) { Logger.Error("Thread:" + Thread.CurrentThread.ManagedThreadId + " crashed.\n", ex); throw; } await Task.Delay(TimeSpan.FromHours(24), CANCEL_TOKEN.Token); }
/// <summary> /// 重要:连接服务端,一般做为入口方法 /// 该方法主要操作一些配置和心跳 /// AlwaysReconnect:始终重试,开启此选项,无论何时,一旦程序在连接不上时都会进行重试,否则只在连接成功后的异常中断时才重试。 /// </summary> /// <returns></returns> public async Task Start(bool AlwaysReconnect = false) { if (AlwaysReconnect) { IsStarted = true; } var oneLiveToken = ONE_LIVE_TOKEN_SRC.Token; //登录功能 string arrangedToken = Global.NO_TOKEN_STRING; while (!oneLiveToken.IsCancellationRequested) { CANCEL_TOKEN_SRC = new CancellationTokenSource(); TRANSFERING_TOKEN_SRC = new CancellationTokenSource(); HEARTBEAT_TOKEN_SRC = new CancellationTokenSource(); _waiter = new TaskCompletionSource <object>(); Router.TimeStamp = Guid.NewGuid(); var appIdIpPortConfig = ClientConfig.Clients; int clientId = 0; //0 获取服务器端口配置 try { await InitServerPorts(); } catch (Exception ex)//出错 重连 { if (IsStarted == false) { StatusChanged(ClientStatus.LoginError, null); return; } else { Logger.Error("获取服务器端口失败:" + ex.Message, ex); await Task.Delay(Global.ClientReconnectInterval, ONE_LIVE_TOKEN_SRC.Token); continue; } } //0.5 处理登录/重登录/匿名登录逻辑 try { //登录 if (CurrentLoginInfo != null) { var loginResult = await Login(); arrangedToken = loginResult.Item1; clientId = loginResult.Item2; } else if (File.Exists(NspClientCachePath)) { //登录缓存 arrangedToken = File.ReadAllText(NspClientCachePath); //TODO 这个token的合法性无法保证,如果服务端删除了用户,而这里缓存还存在,会导致无法登录 //TODO ***** 这是个trick:防止匿名用户被服务端踢了之后无限申请新账号 //TODO 待解决 版本号无法显示的问题 CurrentLoginInfo = null; } else { //匿名登录,未提供登录信息时,使用空用户名密码自动注册并尝试匿名登录 Router.Logger.Debug("未提供登录信息,尝试匿名登录"); CurrentLoginInfo = new LoginInfo() { UserName = "", UserPwd = "" }; var loginResult = await Login(); arrangedToken = loginResult.Item1; clientId = loginResult.Item2; //保存缓存到磁盘 File.WriteAllText(NspClientCachePath, arrangedToken); } } catch (Exception ex)//出错 重连 { if (IsStarted == false) { StatusChanged(ClientStatus.LoginError, null); return; } else { Logger.Error("启动失败:" + ex.Message, ex); await Task.Delay(Global.ClientReconnectInterval, ONE_LIVE_TOKEN_SRC.Token); continue; } } //1.获取配置 ConnectionManager = ServerConnectionManager.Create(clientId); ConnectionManager.CurrentToken = arrangedToken; ConnectionManager.ClientGroupConnected += ServerConnnectionManager_ClientGroupConnected; ConnectionManager.ServerNoResponse = DoServerNoResponse; //下钻事件 ClientModel clientModel = null; // try { //从服务端初始化客户端配置 clientModel = await ConnectionManager.InitConfig(this.ClientConfig).ConfigureAwait(false); } catch (Exception ex) { //TODO 状态码:连接失败 Router.Logger.Error("连接失败:" + ex.Message, ex); //throw; } //HasConnected = true; if (clientModel != null) { int counter = 0; //2.分配配置:appid为0时说明没有分配appid,所以需要分配一个 foreach (var app in appIdIpPortConfig) { if (app.AppId == 0) { app.AppId = clientModel.AppList[counter].AppId; counter++; } } Logger.Debug("****************port list*************"); List <string> tunnelstrs = new List <string>(); foreach (var ap in clientModel.AppList) { var cApp = appIdIpPortConfig.First(obj => obj.AppId == ap.AppId); var tunnelStr = ap.AppId.ToString() + ": " + ClientConfig.ProviderAddress + ":" + ap.Port.ToString() + "=>" + cApp.IP + ":" + cApp.TargetServicePort; Logger.Debug(tunnelStr); tunnelstrs.Add(tunnelStr); } Logger.Debug("**************************************"); _ = ConnectionManager.PollingToProvider(StatusChanged, tunnelstrs); //3.创建心跳连接 _ = ConnectionManager.StartHeartBeats(Global.HeartbeatInterval, HEARTBEAT_TOKEN_SRC.Token, _waiter); IsStarted = true; if (await _waiter.Task.ConfigureAwait(false) is Exception exception) { Router.Logger.Debug($"程序异常终止:{exception.Message}。"); } else { Router.Logger.Debug($"未知异常。"); } } else { Router.Logger.Debug($"程序启动失败。"); //如果程序从未启动过就出错,则终止程序,否则重试。 if (IsStarted == false) { StatusChanged(ClientStatus.Stopped, null); return; } } Router.Logger.Debug($"连接故障,尝试关闭连接并重试"); if (ConnectionManager != null) { ConnectionManager.CloseAllConnections();//关闭所有连接 } //出错重试 await Task.Delay(Global.ClientReconnectInterval, ONE_LIVE_TOKEN_SRC.Token); //TODO 返回错误码 //await Task.Delay(TimeSpan.FromHours(24), CANCEL_TOKEN.CurrentToken).ConfigureAwait(false); Router.Logger.Debug($"连接关闭,开启重试"); } //正常终止 Router.Logger.Debug($"停止重试,循环终止。"); }
private async Task ProcessHttpRequestAsync(HttpListenerContext context) { var request = context.Request; var response = context.Response; //TODO XX 设置该同源策略为了方便调试,真实项目可以确保同源 #if DEBUG response.AddHeader("Access-Control-Allow-Origin", "*"); #endif try { //通过request来的值进行接口调用 string unit = request.RawUrl.Replace("//", ""); if (unit == "/") { unit = INDEX_PAGE; } int idx1 = unit.LastIndexOf("#"); if (idx1 > 0) { unit = unit.Substring(0, idx1); } int idx2 = unit.LastIndexOf("?"); if (idx2 > 0) { unit = unit.Substring(0, idx2); } int idx3 = unit.LastIndexOf("."); //通过后缀获取不同的文件,若无后缀,则调用接口 if (idx3 > 0) { if (!File.Exists(BASE_FILE_PATH + unit)) { Server.Logger.Debug($"未找到文件{BASE_FILE_PATH + unit}"); return; } //mime类型 ProcessMIME(response, unit.Substring(idx3)); //TODO 权限控制(只是控制html权限而已) //读文件优先去缓存读 MemoryStream memoryStream; if (FilesCache.TryGetValue(unit.TrimStart('/'), out memoryStream)) { memoryStream.Position = 0; await memoryStream.CopyToAsync(response.OutputStream); } else { using (FileStream fs = new FileStream(BASE_FILE_PATH + unit, FileMode.Open)) { await fs.CopyToAsync(response.OutputStream); } } } else //url中没有小数点则是接口 { unit = unit.Replace("/", ""); response.ContentEncoding = Encoding.UTF8; //调用接口 用分布类隔离并且用API特性限定安全 object jsonObj; //List<string> qsStrList; int qsCount = request.QueryString.Count; object[] parameters = null; if (qsCount > 0) { parameters = new object[request.QueryString.Count]; for (int i = 0; i < request.QueryString.Count; i++) { parameters[i] = request.QueryString[i]; } } //反射调用API方法 MethodInfo method = null; try { method = this.GetType().GetMethod(unit); if (method == null) { //Server.Logger.Debug($"无效的方法名{unit}"); throw new Exception($"无效的方法名{unit}"); } //TODO 先不校验,方便调试 //if (method.GetCustomAttribute<SecureAttribute>() != null) //{ // if (request.Cookies["NSPTK"] == null) // throw new Exception("用户未登陆。"); // //TODO cookie,根据不同的用户角色分配权限。 // var UserClaims = StringUtil.ConvertStringToTokenClaims(request.Cookies["NSPTK"].Value); // if (string.IsNullOrEmpty(UserClaims.UserKey)) // { // throw new Exception("登陆信息异常。"); // } //} if (method.GetCustomAttribute <APIAttribute>() != null) { response.ContentType = "application/json"; jsonObj = method.Invoke(this, parameters); await response.OutputStream.WriteAsync(HtmlUtil.GetContent(jsonObj.Wrap().ToJsonString())); } else if (method.GetCustomAttribute <FormAPIAttribute>() != null) { response.ContentType = "text/html"; jsonObj = method.Invoke(this, parameters); await response.OutputStream.WriteAsync(HtmlUtil.GetContent(jsonObj.ToString())); } else if (method.GetCustomAttribute <ValidateAPIAttribute>() != null) { response.ContentType = "application/json"; bool validateResult = (bool)method.Invoke(this, parameters); if (validateResult == true) { await response.OutputStream.WriteAsync(HtmlUtil.GetContent("{\"valid\":true}")); } else { await response.OutputStream.WriteAsync(HtmlUtil.GetContent("{\"valid\":false}")); } } else if (method.GetCustomAttribute <FileAPIAttribute>() != null) { response.ContentType = "application/octet-stream"; FileDTO fileDto = method.Invoke(this, parameters) as FileDTO; if (fileDto == null) { throw new Exception("文件返回失败,请查看错误日志。"); } response.Headers.Add("Content-Disposition", "attachment;filename=" + fileDto.FileName); //response.OutputStream.(stream); using (fileDto.FileStream) { await fileDto.FileStream.CopyToAsync(response.OutputStream); } } } catch (Exception ex) { Logger.Error(ex.Message, ex); jsonObj = new Exception(ex.Message + "---" + ex.StackTrace); response.ContentType = "application/json"; await response.OutputStream.WriteAsync(HtmlUtil.GetContent(jsonObj.Wrap().ToJsonString())); } finally { } } } catch (Exception e) { Logger.Error(e.Message, e); throw; } finally { response.OutputStream.Close(); } }
private async Task ProcessHttpRequestAsync(HttpListenerContext context) { string baseFilePath = "./Extension/HttpServerStaticFiles/"; var request = context.Request; var response = context.Response; //TODO XX 设置该同源策略为了方便调试,请确保web项目也位于locahost5671上 response.AddHeader("Access-Control-Allow-Origin", "http://localhost:5671"); try { //TODO ***通过request来的值进行接口调用 string unit = request.RawUrl.Replace("//", ""); int idx1 = unit.LastIndexOf("#"); if (idx1 > 0) { unit = unit.Substring(0, idx1); } int idx2 = unit.LastIndexOf("?"); if (idx2 > 0) { unit = unit.Substring(0, idx2); } int idx3 = unit.LastIndexOf("."); //TODO 通过后缀获取不同的文件,若无后缀,则调用接口 if (idx3 > 0) { if (!File.Exists(baseFilePath + unit)) { Server.Logger.Debug($"未找到文件{baseFilePath + unit}"); return; } //mime类型 ProcessMIME(response, unit.Substring(idx3)); using (FileStream fs = new FileStream(baseFilePath + unit, FileMode.Open)) { await fs.CopyToAsync(response.OutputStream); } } else { unit = unit.Replace("/", ""); response.ContentEncoding = Encoding.UTF8; response.ContentType = "application/json"; //TODO XXXXXX 调用接口 接下来要用分布类隔离并且用API特性限定安全 object jsonObj; //List<string> qsStrList; int qsCount = request.QueryString.Count; object[] parameters = null; if (qsCount > 0) { parameters = new object[request.QueryString.Count]; for (int i = 0; i < request.QueryString.Count; i++) { parameters[i] = request.QueryString[i]; } } // request.QueryString[0] try { jsonObj = this.GetType().GetMethod(unit).Invoke(this, parameters); } catch (Exception e) { Logger.Error(e.Message, e); jsonObj = e.Message + "---" + e.StackTrace; } //getJson //var json = GetClientsInfoJson(); //无返回值则返回默认数据。 //if (jsonObj == null) await response.OutputStream.WriteAsync(HtmlUtil.GetContent("")); await response.OutputStream.WriteAsync(HtmlUtil.GetContent(jsonObj.Wrap().ToJsonString())); //await response.OutputStream.WriteAsync(HtmlUtil.GetContent(request.RawUrl)); // response.OutputStream.Close(); } //suffix = unit.Substring(unit.LastIndexOf(".")+1,) } catch (Exception e) { Logger.Error(e.Message, e); throw; } finally { response.OutputStream.Close(); } }
/// <summary> /// 重要:连接服务端,一般做为入口方法 /// 该方法主要操作一些配置和心跳 /// </summary> /// <returns></returns> public async Task Start() { var oneLiveToken = ONE_LIVE_TOKEN_SRC.Token; while (!oneLiveToken.IsCancellationRequested) { CANCEL_TOKEN_SRC = new CancellationTokenSource(); TRANSFERING_TOKEN_SRC = new CancellationTokenSource(); HEARTBEAT_TOKEN_SRC = new CancellationTokenSource(); _waiter = new TaskCompletionSource <object>(); var appIdIpPortConfig = ClientConfig.Clients; int clientId = 0; //0.5 如果有文件,取出缓存中的clientid try { if (File.Exists(NSMART_CLIENT_CACHE_PATH)) { using (var stream = File.OpenRead(NSMART_CLIENT_CACHE_PATH)) { byte[] bytes = new byte[2]; stream.Read(bytes, 0, bytes.Length); clientId = StringUtil.DoubleBytesToInt(bytes); } } } catch (Exception ex) { Logger.Error(ex.Message, ex); } //1.获取配置 ConnectionManager = ServerConnnectionManager.Create(clientId); ConnectionManager.ClientGroupConnected += ServerConnnectionManager_ClientGroupConnected; ConnectionManager.ServerNoResponse = DoServerNoResponse; //下钻事件 ClientModel clientModel = null; // try { //非第一次则算作重连,发送clientid过去 clientModel = await ConnectionManager.InitConfig(this.ClientConfig).ConfigureAwait(false); } catch (Exception ex) { //TODO 状态码:连接失败 Router.Logger.Error("连接失败:" + ex.Message, ex); //throw; } //HasConnected = true; if (clientModel != null) { int counter = 0; //1.5 写入缓存 File.WriteAllBytes(NSMART_CLIENT_CACHE_PATH, StringUtil.IntTo2Bytes(clientModel.ClientId)); //2.分配配置:appid为0时说明没有分配appid,所以需要分配一个 foreach (var app in appIdIpPortConfig) { if (app.AppId == 0) { app.AppId = clientModel.AppList[counter].AppId; counter++; } } Logger.Debug("****************port list*************"); List <string> tunnelstrs = new List <string>(); foreach (var ap in clientModel.AppList) { var cApp = appIdIpPortConfig.First(obj => obj.AppId == ap.AppId); var tunnelStr = ap.AppId.ToString() + ": " + ClientConfig.ProviderAddress + ":" + ap.Port.ToString() + "=>" + cApp.IP + ":" + cApp.TargetServicePort; Logger.Debug(tunnelStr); tunnelstrs.Add(tunnelStr); } Logger.Debug("**************************************"); ConnectionManager.PollingToProvider(StatusChanged, tunnelstrs); //3.创建心跳连接 ConnectionManager.StartHeartBeats(Global.HeartbeatInterval, HEARTBEAT_TOKEN_SRC.Token); //try //{ // await pollingTask.ConfigureAwait(false); //} //catch (Exception ex) //{ // Logger.Error("Thread:" + Thread.CurrentThread.ManagedThreadId + " crashed.\n", ex); // throw; //} IsStarted = true; Exception exception = await _waiter.Task.ConfigureAwait(false) as Exception; Router.Logger.Debug($"程序异常终止:{exception.Message}。"); } else { Router.Logger.Debug($"程序启动失败。"); //如果程序从未启动过就出错,则终止程序,否则重试。 if (IsStarted == false) { StatusChanged(ClientStatus.Stopped, null); return; } } //出错重试 await Task.Delay(3000, ONE_LIVE_TOKEN_SRC.Token); //TODO 返回错误码 //await Task.Delay(TimeSpan.FromHours(24), CANCEL_TOKEN.Token).ConfigureAwait(false); } //正常终止 }
private async Task ProcessHttpRequestAsync(HttpListenerContext context) { var request = context.Request; var response = context.Response; //TODO XX 设置该同源策略为了方便调试,请确保web项目也位于locahost5671上 #if DEBUG response.AddHeader("Access-Control-Allow-Origin", "*"); #endif try { //TODO ***通过request来的值进行接口调用 string unit = request.RawUrl.Replace("//", ""); if (unit == "/") { unit = INDEX_PAGE; } int idx1 = unit.LastIndexOf("#"); if (idx1 > 0) { unit = unit.Substring(0, idx1); } int idx2 = unit.LastIndexOf("?"); if (idx2 > 0) { unit = unit.Substring(0, idx2); } int idx3 = unit.LastIndexOf("."); //TODO 通过后缀获取不同的文件,若无后缀,则调用接口 if (idx3 > 0) { if (!File.Exists(BASE_FILE_PATH + unit)) { Server.Logger.Debug($"未找到文件{BASE_FILE_PATH + unit}"); return; } //mime类型 ProcessMIME(response, unit.Substring(idx3)); //读文件优先去缓存读 MemoryStream memoryStream; if (FilesCache.TryGetValue(unit.TrimStart('/'), out memoryStream)) { memoryStream.Position = 0; await memoryStream.CopyToAsync(response.OutputStream); } else { using (FileStream fs = new FileStream(BASE_FILE_PATH + unit, FileMode.Open)) { await fs.CopyToAsync(response.OutputStream); } } } else { unit = unit.Replace("/", ""); response.ContentEncoding = Encoding.UTF8; //TODO XXXXXX 调用接口 接下来要用分布类隔离并且用API特性限定安全 object jsonObj; //List<string> qsStrList; int qsCount = request.QueryString.Count; object[] parameters = null; if (qsCount > 0) { parameters = new object[request.QueryString.Count]; for (int i = 0; i < request.QueryString.Count; i++) { parameters[i] = request.QueryString[i]; } } // request.QueryString[0] MethodInfo method = null; try { method = this.GetType().GetMethod(unit); if (method == null) { Server.Logger.Debug($"无效的方法名{unit}"); } if (method.GetCustomAttribute <APIAttribute>() != null) { response.ContentType = "application/json"; jsonObj = method.Invoke(this, parameters); await response.OutputStream.WriteAsync(HtmlUtil.GetContent(jsonObj.Wrap().ToJsonString())); } else if (method.GetCustomAttribute <FormAPIAttribute>() != null) { response.ContentType = "text/html"; jsonObj = method.Invoke(this, parameters); await response.OutputStream.WriteAsync(HtmlUtil.GetContent(jsonObj.ToString())); } } catch (Exception ex) { Logger.Error(ex.Message, ex); jsonObj = new Exception(ex.Message + "---" + ex.StackTrace); response.ContentType = "application/json"; await response.OutputStream.WriteAsync(HtmlUtil.GetContent(jsonObj.Wrap().ToJsonString())); } } //suffix = unit.Substring(unit.LastIndexOf(".")+1,) } catch (Exception e) { Logger.Error(e.Message, e); throw; } finally { response.OutputStream.Close(); } }
/// <summary> /// 重要:连接服务端,一般做为入口方法 /// 该方法主要操作一些配置和心跳 /// AlwaysReconnect:始终重试,开启此选项,无论何时,一旦程序在连接不上时都会进行重试,否则只在连接成功后的断线时才重试。 /// </summary> /// <returns></returns> public async Task Start(bool AlwaysReconnect = false) { if (AlwaysReconnect) { IsStarted = true; } var oneLiveToken = ONE_LIVE_TOKEN_SRC.Token; //登陆功能 string arrangedToken = Global.NO_TOKEN_STRING; while (!oneLiveToken.IsCancellationRequested) { CANCEL_TOKEN_SRC = new CancellationTokenSource(); TRANSFERING_TOKEN_SRC = new CancellationTokenSource(); HEARTBEAT_TOKEN_SRC = new CancellationTokenSource(); _waiter = new TaskCompletionSource <object>(); var appIdIpPortConfig = ClientConfig.Clients; int clientId = 0; //0.5 如果有文件,取出缓存中的clientid try { //登陆缓存 if (File.Exists(NSMART_CLIENT_CACHE_PATH)) { using (var stream = File.OpenRead(NSMART_CLIENT_CACHE_PATH)) { byte[] bytes = new byte[2]; stream.Read(bytes, 0, bytes.Length); clientId = StringUtil.DoubleBytesToInt(bytes); } } //登陆 if (CurrentLoginInfo != null) { NSPDispatcher disp = new NSPDispatcher(); var result = await disp.LoginFromClient(CurrentLoginInfo.UserName, CurrentLoginInfo.UserPwd); if (result.State == 1) { Router.Logger.Debug("登陆成功"); var data = result.Data; arrangedToken = data.Token; Router.Logger.Debug($"服务端版本号:{data.Version},当前适配版本号{Global.NSmartProxyServerName}"); clientId = int.Parse(data.Userid); } else { throw new Exception("登陆失败,服务端返回错误如下:" + result.Msg); } } else { Router.Logger.Debug("为提供登陆信息,尝试匿名登陆"); } } catch (Exception ex) { Logger.Error(ex.Message, ex); } //1.获取配置 ConnectionManager = ServerConnectionManager.Create(clientId); ConnectionManager.CurrentToken = arrangedToken; ConnectionManager.ClientGroupConnected += ServerConnnectionManager_ClientGroupConnected; ConnectionManager.ServerNoResponse = DoServerNoResponse; //下钻事件 ClientModel clientModel = null; // try { //非第一次则算作重连,发送clientid过去 clientModel = await ConnectionManager.InitConfig(this.ClientConfig).ConfigureAwait(false); } catch (Exception ex) { //TODO 状态码:连接失败 Router.Logger.Error("连接失败:" + ex.Message, ex); //throw; } //HasConnected = true; if (clientModel != null) { int counter = 0; //1.5 写入缓存 File.WriteAllBytes(NSMART_CLIENT_CACHE_PATH, StringUtil.IntTo2Bytes(clientModel.ClientId)); //2.分配配置:appid为0时说明没有分配appid,所以需要分配一个 foreach (var app in appIdIpPortConfig) { if (app.AppId == 0) { app.AppId = clientModel.AppList[counter].AppId; counter++; } } Logger.Debug("****************port list*************"); List <string> tunnelstrs = new List <string>(); foreach (var ap in clientModel.AppList) { var cApp = appIdIpPortConfig.First(obj => obj.AppId == ap.AppId); var tunnelStr = ap.AppId.ToString() + ": " + ClientConfig.ProviderAddress + ":" + ap.Port.ToString() + "=>" + cApp.IP + ":" + cApp.TargetServicePort; Logger.Debug(tunnelStr); tunnelstrs.Add(tunnelStr); } Logger.Debug("**************************************"); ConnectionManager.PollingToProvider(StatusChanged, tunnelstrs); //3.创建心跳连接 ConnectionManager.StartHeartBeats(Global.HeartbeatInterval, HEARTBEAT_TOKEN_SRC.Token); IsStarted = true; Exception exception = await _waiter.Task.ConfigureAwait(false) as Exception; if (exception != null) { Router.Logger.Debug($"程序异常终止:{exception.Message}。"); } else { Router.Logger.Debug($"未知异常。"); } } else { Router.Logger.Debug($"程序启动失败。"); //如果程序从未启动过就出错,则终止程序,否则重试。 if (IsStarted == false) { StatusChanged(ClientStatus.Stopped, null); return; } } Router.Logger.Debug($"连接故障,尝试关闭连接并重试"); if (ConnectionManager != null) { ConnectionManager.CloseAllConnections();//关闭所有连接 } //出错重试 await Task.Delay(Global.ClientReconnectInterval, ONE_LIVE_TOKEN_SRC.Token); //TODO 返回错误码 //await Task.Delay(TimeSpan.FromHours(24), CANCEL_TOKEN.CurrentToken).ConfigureAwait(false); Router.Logger.Debug($"连接关闭,开启重试"); } //正常终止 Router.Logger.Debug($"停止重试,循环终止。"); }
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { Logger.Error(e.Exception.ToString(), e.Exception); }