コード例 #1
0
        private void ConnectAsync(WebSocket ws)
        {
            if (ws == null)
            {
                return;
            }
            if (ws.ReadyState == WebSocketState.Open)
            {
                return;
            }
            // WebSocketSharp内部限定了连接重试次数,这不符合我们的业务逻辑,这里通过反射赋值使WebSocketSharp的重试次数限制失效。
            _retryCountForConnectFieldInfo.SetValue(ws, 1);
            WsUserName userName = new WsUserName {
                ClientType        = _appType,
                ClientVersion     = EntryAssemblyInfo.CurrentVersionStr,
                ClientId          = NTMinerRegistry.GetClientId(_appType),
                UserId            = _preOuterUserId,
                IsBinarySupported = true
            };
            string userNameJson = VirtualRoot.JsonSerializer.Serialize(userName);
            string password     = string.Empty;

            if (_appType == NTMinerAppType.MinerStudio)
            {
                password = RpcRoot.RpcUser.Password;
            }
            string base64String = Convert.ToBase64String(Encoding.UTF8.GetBytes(userNameJson));

            password = HashUtil.Sha1(base64String + password);
            // SetCredentials要求username不能带:号,所以必须编码
            ws.SetCredentials(base64String, password, preAuth: true);
            LastTryOn = DateTime.Now;
            ws.ConnectAsync();
        }
コード例 #2
0
 public AbstractWsClient(NTMinerAppType appType)
 {
     _appType  = appType;
     _clientId = NTMinerRegistry.GetClientId(appType);
     VirtualRoot.BuildEventPath <Per1SecondEvent>("重试Ws连接的秒表倒计时", LogEnum.None, typeof(VirtualRoot), PathPriority.Normal, path: message => {
         if (_nextTrySecondsDelay > 0)
         {
             _nextTrySecondsDelay--;
         }
     });
     VirtualRoot.BuildEventPath <Per10SecondEvent>("周期检查Ws连接", LogEnum.None, typeof(VirtualRoot), PathPriority.Normal,
                                                   path: message => {
         if (_ws == null || _ws.ReadyState != WebSocketState.Open)
         {
             if (_continueCount >= _failConnCount)
             {
                 _continueCount = 0;
                 OpenOrCloseWs();
             }
             else
             {
                 _continueCount++;
             }
         }
     });
     // 20秒是个不错的值,即不太频繁,也不太少
     VirtualRoot.BuildEventPath <Per20SecondEvent>("周期Ws Ping", LogEnum.None, typeof(VirtualRoot), PathPriority.Normal, path: message => {
         if (_ws != null && _ws.ReadyState == WebSocketState.Open)
         {
             // 或者_ws.IsAlive,因为_ws.IsAlive内部也是一个Ping,所以用Ping从而显式化这里有个网络请求
             Task.Factory.StartNew(() => {
                 if (!_ws.Ping())
                 {
                     _ws.CloseAsync(CloseStatusCode.Away);
                 }
             });
         }
     });
     VirtualRoot.BuildEventPath <AppExitEvent>("退出程序时关闭Ws连接", LogEnum.DevConsole, this.GetType(), PathPriority.Normal, path: message => {
         _ws?.CloseAsync(CloseStatusCode.Normal, "客户端程序退出");
     });
     NetworkChange.NetworkAvailabilityChanged += (object sender, NetworkAvailabilityEventArgs e) => {
         if (e.IsAvailable)
         {
             1.SecondsDelay().ContinueWith(t => {
                 OpenOrCloseWs(isResetFailCount: true);
             });
         }
     };
     /// 1,进程启动后第一次连接时;
     NeedReWebSocket();
     OpenOrCloseWs();
 }
コード例 #3
0
 public void ReClientIdAsync(NTMinerAppType appType)
 {
     RpcRoot.JsonRpc.FirePostAsync(
         NTKeyword.Localhost,
         NTKeyword.NTMinerDaemonPort,
         _controllerName,
         nameof(INTMinerDaemonController.ReClientId),
         new Dictionary <string, string> {
         ["newClientId"] = NTMinerRegistry.GetClientId(appType).ToString()
     },
         data: null,
         timeountMilliseconds: 3000);
 }
コード例 #4
0
ファイル: UserSet.cs プロジェクト: kissthink/ntminer
 /// <summary>
 /// 同步方法
 /// </summary>
 /// <param name="clientId"></param>
 /// <returns></returns>
 private static List <UserData> GetUsers()
 {
     try {
         DataRequest <Guid?> request = new DataRequest <Guid?> {
             Data = NTMinerRegistry.GetClientId()
         };
         using (HttpClient client = new HttpClient()) {
             client.Timeout = TimeSpan.FromMilliseconds(2000);
             Task <HttpResponseMessage>      message  = client.PostAsJsonAsync($"http://{NTMinerRegistry.GetControlCenterHost()}:{VirtualRoot.ControlCenterPort}/api/ControlCenter/Users", request);
             DataResponse <List <UserData> > response = message.Result.Content.ReadAsAsync <DataResponse <List <UserData> > >().Result;
             if (response != null && response.Data != null)
             {
                 return(response.Data);
             }
         }
     }
     catch (Exception e) {
         Logger.ErrorDebugLine(e);
     }
     return(new List <UserData>());
 }
コード例 #5
0
 /// <summary>
 /// 同步方法
 /// </summary>
 /// <param name="clientId"></param>
 /// <returns></returns>
 private static List <UserData> GetUsers()
 {
     try {
         DataRequest <Guid?> request = new DataRequest <Guid?> {
             LoginName = string.Empty,
             Data      = NTMinerRegistry.GetClientId()
         };
         using (HttpClient client = new HttpClient()) {
             Task <HttpResponseMessage>      message  = client.PostAsJsonAsync($"http://{NTMinerRegistry.GetControlCenterHost()}:{WebApiConst.ControlCenterPort}/api/ControlCenter/Users", request);
             DataResponse <List <UserData> > response = message.Result.Content.ReadAsAsync <DataResponse <List <UserData> > >().Result;
             if (response != null && response.Data != null)
             {
                 return(response.Data);
             }
         }
     }
     catch (Exception e) {
         e = e.GetInnerException();
         Logger.ErrorDebugLine(e.Message, e);
     }
     return(new List <UserData>());
 }
コード例 #6
0
        public void GetJsonFileVersionAsync(NTMinerAppType appType, string key, Action <ServerStateResponse> callback)
        {
            HashSet <string> macAddresses = new HashSet <string>();

            foreach (var localIp in VirtualRoot.LocalIpSet.AsEnumerable().ToArray())
            {
                macAddresses.Add(localIp.MACAddress);
            }
            JsonFileVersionRequest request = new JsonFileVersionRequest {
                Key        = key,
                ClientId   = NTMinerRegistry.GetClientId(appType),
                MACAddress = macAddresses.ToArray()
            };

            RpcRoot.JsonRpc.PostAsync(
                RpcRoot.OfficialServerHost,
                RpcRoot.OfficialServerPort,
                _controllerName,
                nameof(IAppSettingController.GetServerState),
                request,
                callback: (ServerStateResponse response, Exception e) => {
                if (e != null)
                {
                    Logger.ErrorDebugLine(e);
                }
                if (response == null)
                {
                    response = ServerStateResponse.Empty;
                    Logger.ErrorWriteLine("询问服务器状态失败,请检查网络。");
                }
                if (response.NeedReClientId)
                {
                    NTMinerRegistry.ReClientId(ClientAppType.AppType);
                    RpcRoot.Client.NTMinerDaemonService.ReClientIdAsync(appType);
                    Logger.InfoDebugLine("检测到本机标识存在重复,已重新生成");
                }
                callback?.Invoke(response);
            }, timeountMilliseconds: 10 * 1000);
        }
コード例 #7
0
ファイル: AbstractWsClient.cs プロジェクト: SZP1206/NtMiner
        /// <summary>
        /// 这是一次彻底的重连,重新获取服务器地址的重连,以下情况下才会调用该方法:
        /// 1,进程启动后第一次连接时;
        /// 2,连不上服务器时;
        /// 3,收到服务器的WsMessage.ReGetServerAddress类型的消息时;
        /// </summary>
        /// <returns></returns>
        private void NewWebSocket(Action <WebSocket> callback)
        {
            RpcRoot.OfficialServer.WsServerNodeService.GetNodeAddressAsync(NTMinerRegistry.GetClientId(_appType), _outerUserId, (response, ex) => {
                LastTryOn = DateTime.Now;
                if (!response.IsSuccess())
                {
                    IncreaseFailCount();
                    UpdateNextTrySecondsDelay();
                    string description;
                    if (response == null || response.ReasonPhrase == null)
                    {
                        description = "网络错误";
                    }
                    else
                    {
                        description = response.ReadMessage(ex);
                    }
                    UpdateWsStateAsync(description, toOut: false);
                    callback?.Invoke(null);
                    // 退出
                    return;
                }
                string server = response.Data;
                if (string.IsNullOrEmpty(server))
                {
                    IncreaseFailCount();
                    UpdateNextTrySecondsDelay();
                    UpdateWsStateAsync("服务器不在线", toOut: false);
                    callback?.Invoke(null);
                    // 退出
                    return;
                }

                var ws     = new WebSocket($"ws://{server}/{_appType.GetName()}");
                ws.OnOpen += (sender, e) => {
                    ResetFailCount();
                    UpdateWsStateAsync("连接服务器成功", toOut: false);
                };
                ws.OnMessage += (sender, e) => {
                    if (_ws != ws)
                    {
                        return;
                    }
                    #region
                    if (e.IsPing)
                    {
                        return;
                    }
                    WsMessage message = null;
                    if (e.IsBinary)
                    {
                        message = VirtualRoot.BinarySerializer.Deserialize <WsMessage>(e.RawData);
                    }
                    else  // 此时一定IsText,因为取值只有IsBinary、IsPing、IsText这三种
                    {
                        if (string.IsNullOrEmpty(e.Data) || e.Data[0] != '{' || e.Data[e.Data.Length - 1] != '}')
                        {
                            return;
                        }
                        message = VirtualRoot.JsonSerializer.Deserialize <WsMessage>(e.Data);
                    }
                    if (message == null)
                    {
                        return;
                    }
                    switch (_appType)
                    {
                    case NTMinerAppType.MinerClient:
                        if (message.Type == WsMessage.UpdateAESPassword)
                        {
                            if (message.TryGetData(out AESPassword aesPassword))
                            {
                                aesPassword.Password = Cryptography.RSAUtil.DecryptString(aesPassword.Password, aesPassword.PublicKey);
                                _aesPassword         = aesPassword;
                            }
                            return;
                        }
                        if (_aesPassword == null)
                        {
                            return;
                        }
                        if (message.Sign != message.CalcSign(_aesPassword.Password))
                        {
                            UpdateWsStateAsync(description: "来自群控的消息签名错误", toOut: true);
                            return;
                        }
                        break;
コード例 #8
0
        /// <summary>
        /// 这是一次彻底的重连,重新获取服务器地址的重连,以下情况下才会调用该方法:
        /// 1,进程启动后第一次连接时;
        /// 2,连不上服务器时;
        /// 3,收到服务器的WsMessage.ReGetServerAddress类型的消息时;
        /// </summary>
        /// <returns></returns>
        private void NewWebSocket()
        {
            if (_ws != null)
            {
                return;
            }
            RpcRoot.OfficialServer.WsServerNodeService.GetNodeAddressAsync(NTMinerRegistry.GetClientId(_appType), _preOuterUserId, (response, ex) => {
                if (_ws == null)
                {
                    lock (_wsLocker) {
                        if (_ws == null)
                        {
                            LastTryOn   = DateTime.Now;
                            _wsServerIp = string.Empty;

                            #region 网络错误或没有获取到WsServer节点时退出
                            if (!response.IsSuccess())
                            {
                                // 没有获取到该矿机的WsServer分片节点,递增失败次数以增大重试延迟周期
                                IncreaseFailCount();
                                UpdateNextTrySecondsDelay();
                                string description;
                                if (response == null || response.ReasonPhrase == null)
                                {
                                    description = "网络错误";
                                }
                                else
                                {
                                    description = response.ReadMessage(ex);
                                }
                                UpdateWsStateAsync(description, toOut: false);
                                // 退出
                                return;
                            }
                            string server = response.Data;
                            if (string.IsNullOrEmpty(server))
                            {
                                // 没有获取到该矿机的WsServer分片节点,递增失败次数以增大重试延迟周期
                                IncreaseFailCount();
                                UpdateNextTrySecondsDelay();
                                UpdateWsStateAsync("服务器不在线", toOut: false);
                                // 退出
                                return;
                            }
                            _wsServerIp = server;
                            #endregion

                            var ws = new WebSocket($"ws://{server}/{_appType.GetName()}")
                            {
                                Compression = CompressionMethod.Deflate
                            };
                            ws.Log.File   = System.IO.Path.Combine(TempPath.TempLogsDirFullName, NTKeyword.WebSocketSharpMinerClientLogFileName);
                            ws.Log.Output = WebSocketSharpOutput;
                            ws.OnOpen    += new EventHandler(Ws_OnOpen);
                            ws.OnMessage += new EventHandler <MessageEventArgs>(Ws_OnMessage);
                            ws.OnError   += new EventHandler <ErrorEventArgs>(Ws_OnError);
                            ws.OnClose   += new EventHandler <CloseEventArgs>(Ws_OnClose);

                            ConnectAsync(ws);
                            _ws = ws;
                        }
                    }
                }
            });
        }