using System; using System.Linq; using System.Text; using System.Threading; using System.Xml; using Api.Framework.Utils; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using WebSocket = WebSocketSharp.WebSocket; using CsharpHttpHelper; using WebSocketSharp; namespace Api.Framework { /// /// 云通知数据 /// public class CloudNoticeEventArgs : EventArgs { /// /// 通知数据ID,通过这个排重 /// public string Id { get; set; } /// /// 通知内容 /// public string Body { get; set; } /// /// 命令ID /// public string CommonId { get; set; } /// /// 发布时间 /// public DateTime CreateDateTime { get; set; } /// /// 信号通道 /// public string Channel { get; set; } } /// /// 发送Ack模式通知数据 /// public class AckNoticeData : EventArgs { /// /// ID /// public string Id { get; set; } /// /// 命令ID /// public string CommonId { get; set; } /// /// 信号道 /// public string Channel { get; set; } /// /// 数据 /// public string Data { get; set; } /// /// 生成时间 /// public DateTime CreateDateTime { get; set; } /// /// 标记被删除 /// public bool IsRemove { get; set; } /// /// 重试 /// public bool IsRetry { get; set; } } /// /// 通知客户端 /// public class NoticeSocketClient { /// /// 获取数据 /// /// /// public string GetData(string key) { var http = new HttpHelper(); var html = http.GetHtml($"http://event.api.52cmg.cn/api/TransferData/Get?key={key}&rd={DateTime.Now.Ticks}").Html; var rest = JObject.Parse(html); //if (!(rest["Ok"] ?? false).Value() throw new Exception(html); //return (rest["Data"] ?? string.Empty).Value(); //EventClient.OnEvent($"获取淘客域名数据", $"{html}"); if (!(rest["Ok"] ?? false).Value()) throw new Exception(html); return (rest["Data"] ?? string.Empty).Value(); } } /// /// 远程调度服务连接 /// public class RemoteCloudConnectService { /// /// 初始化 /// public void Initialize() { this.Url = "ws://event.api.52cmg.cn"; ThreadPool.QueueUserWorkItem(o => { DisputeConnect(); }); } /// /// 争抢连接 /// private void DisputeConnect() { try { Start(); } finally { } } /// /// 地址 /// public string Url { get; set; } /// /// 启动 连接 /// public void Start() { while (true) { if (Connect()) { return; } Thread.Sleep(5000); } } /// /// 是否正常连接 /// public bool IsConnect { get; private set; } /// /// 收到消息 /// public event Action OnMessage; /// /// 收到云端通知事件 /// public event EventHandler CloudNoticeEvent; /// /// 连接打开 /// public event Action OnOpen; /// /// websocket /// private WebSocket _ws; /// /// ping /// private string _pingThradId; /// /// ping失败次数 /// public int PingFailureCount { get; set; } /// /// 重新连接次数 /// public int ReconnectionCount { get; set; } /// /// 连接ID /// public string ConnectId { get; set; } = Guid.NewGuid().ToString("N"); /// /// 连接服务器 /// private bool Connect() { try { if (IsConnect) { return true; } if (string.IsNullOrWhiteSpace(Url)) { return false; } _ws = new WebSocket(this.Url + "/api/push?id=" + this.ConnectId); _ws.OnOpen += _ws_OnOpen; _ws.OnClose += _ws_OnClose; _ws.OnMessage += _ws_OnMessage; _ws.OnError += _ws_OnError; _ws.Connect(); Thread.Sleep(1000); if (!IsConnect) { return false; } //连接成功 StartPing(); } catch (Exception e) { // _log.Error(e); } return true; } /// /// 错误信息 /// /// /// /// private void _ws_OnError(object sender, ErrorEventArgs e) { //_log.Warn(e.Exception, "知易云服务连接断开" + e.Message); this.IsConnect = false; OnReconnection(); } /// /// 连接断开 /// /// /// private void _ws_OnClose(object sender, CloseEventArgs e) { // _log.Warn("知易云服务连接断开"); this.IsConnect = false; OnReconnection(); } /// /// 连接打开 /// /// /// private void _ws_OnOpen(object sender, EventArgs e) { // _log.Info("知易云服务连接成功"); this.IsConnect = true; OnOpen?.Invoke(); } /// /// 启动Ping /// public void StartPing() { // _log.Info("启动心跳检测"); var tr = new Thread(() => { var id = _pingThradId = Guid.NewGuid().ToString(); while (id == _pingThradId) { Thread.Sleep(1000 * 10); if (_ws == null) { return; } try { if (_ws.ReadyState == WebSocketState.Open) { _ws.Send("\u0001\u0002"); this.PingFailureCount = 0; } else { this.PingFailureCount = this.PingFailureCount + 1; } } catch { // ignored this.PingFailureCount = this.PingFailureCount + 1; } finally { if (this.PingFailureCount > 5) { this.IsConnect = false; //_log.Error("心跳异常连接断开"); _ws?.Close(); } } } }); tr.IsBackground = true; tr.Start(); } /// /// 是否允许重新连接 /// public bool AllowReconnected { get; set; } = true; private bool _isBeginRconnection; private readonly object _lockReconnection = new object(); private void OnReconnection() { if (_isBeginRconnection || !AllowReconnected) return; lock (_lockReconnection) { if (_isBeginRconnection || !AllowReconnected) return; _onReconnection(); } } private void _onReconnection() { if (_isBeginRconnection || !AllowReconnected) return; try { _isBeginRconnection = true; //_log.Debug("重连中..."); while (true) { Thread.Sleep(1000 * 5); if (AllowReconnected && !IsConnect) { this.ReconnectionCount++; if (Connect()) { // _log.Debug("重连成功"); break; } } } } finally { _isBeginRconnection = false; } } /// /// 收到消息 /// /// /// /// private void _ws_OnMessage(object sender, MessageEventArgs e) { if (e.IsText) { var index = e.Data.IndexOf("\u0000", StringComparison.Ordinal); if (index <= -1) { return; } LogHelper.GetSingleObj().Info("接收到通知",$"{e.Data}"); var commonId = e.Data.Substring(0, index); var body = e.Data.Substring(index + 1); if (commonId == "notice")//收到通知 { var ackNoticeData = Newtonsoft.Json.JsonConvert.DeserializeObject(body); if (ackNoticeData == null) { return; } if (ackNoticeData.IsRemove) { return; } this.CloudNoticeEvent?.Invoke(this, new CloudNoticeEventArgs() { Id = ackNoticeData.Id, Body = ackNoticeData.Data, CommonId = ackNoticeData.CommonId, CreateDateTime = ackNoticeData.CreateDateTime, Channel = ackNoticeData.Channel }); _ws.Send("notice_ack\u0000" + ackNoticeData.Id);//回复确认标示 return; } } this.OnMessage?.Invoke(e); } /// /// 发送字节 /// /// public void SendBytes(byte[] bytes) { if (IsConnect) { _ws.Send(bytes); } } /// /// 发送字符串 /// /// public void SendString(string context) { if (IsConnect) { _ws.Send(context); } } } }