2022-09-20 03:10:29 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Xml;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
using WebSocket = WebSocketSharp.WebSocket;
|
|
|
|
|
using CsharpHttpHelper;
|
2023-02-01 06:18:07 +00:00
|
|
|
|
using WebSocketSharp;
|
2022-09-20 03:10:29 +00:00
|
|
|
|
|
|
|
|
|
namespace Api.Framework
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通知客户端
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class NoticeSocketClient
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 发送Ack模式通知数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class AckNoticeData : EventArgs
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// ID
|
|
|
|
|
/// </summary>
|
|
|
|
|
public string Id { get; set; }
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 命令ID
|
|
|
|
|
/// </summary>
|
|
|
|
|
public string CommonId { get; set; }
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 信号道
|
|
|
|
|
/// </summary>
|
|
|
|
|
public string Channel { get; set; }
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
public string Data { get; set; }
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 生成时间
|
|
|
|
|
/// </summary>
|
|
|
|
|
public DateTime CreateDateTime { get; set; }
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 标记被删除
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool IsRemove { get; set; }
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 重试
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool IsRetry { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 构造函数
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="host"></param>
|
|
|
|
|
/// <param name="channel"></param>
|
|
|
|
|
public NoticeSocketClient(string host, params string[] channel)
|
|
|
|
|
{
|
|
|
|
|
this._host = host;
|
|
|
|
|
this._channels = channel.ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private readonly string[] _channels;
|
|
|
|
|
private readonly string _host;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 连接对象
|
|
|
|
|
/// </summary>
|
|
|
|
|
private WebSocket _websocket;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 连接状态
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool IsConnected => (_websocket != null && _websocket.IsAlive);
|
|
|
|
|
|
2023-02-01 06:18:07 +00:00
|
|
|
|
private string ClientId { get; set; } = Guid.NewGuid().ToString("N");
|
|
|
|
|
|
2022-09-20 03:10:29 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 连接
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void Connect()
|
|
|
|
|
{
|
|
|
|
|
if (IsConnected)
|
|
|
|
|
{
|
|
|
|
|
_websocket.OnOpen -= _websocket_OnOpen;
|
|
|
|
|
_websocket.OnMessage -= _websocket_OnMessage;
|
|
|
|
|
_websocket?.Close();
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-01 06:18:07 +00:00
|
|
|
|
_websocket = new WebSocket($"ws://{this._host}/api/push?id={ClientId}");
|
2022-09-20 03:10:29 +00:00
|
|
|
|
_websocket.OnOpen += _websocket_OnOpen;
|
2023-02-01 06:18:07 +00:00
|
|
|
|
_websocket.OnError += _websocket_OnError;
|
|
|
|
|
_websocket.OnClose += _websocket_OnClose;
|
2022-09-20 03:10:29 +00:00
|
|
|
|
_websocket.OnMessage += _websocket_OnMessage;
|
|
|
|
|
_websocket.Connect();
|
2023-02-01 06:18:07 +00:00
|
|
|
|
_pingId = Guid.NewGuid().ToString("N");
|
|
|
|
|
_thread = new Thread(Ping)
|
2022-09-20 03:10:29 +00:00
|
|
|
|
{
|
2023-02-01 06:18:07 +00:00
|
|
|
|
IsBackground = true
|
|
|
|
|
};
|
|
|
|
|
_thread.Start();
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 连接断开
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void _websocket_OnClose(object sender, CloseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
//断开自动重连
|
|
|
|
|
this.Connect();
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 出现连接错误
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void _websocket_OnError(object sender, ErrorEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
//断开自动重连
|
|
|
|
|
this.Connect();
|
2022-09-20 03:10:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 收到消息事件
|
|
|
|
|
/// </summary>
|
|
|
|
|
public event EventHandler<AckNoticeData> OnMessageEvent;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 连接成功事件
|
|
|
|
|
/// </summary>
|
|
|
|
|
public event EventHandler<EventArgs> OnConnectedEvent;
|
|
|
|
|
|
|
|
|
|
private void _websocket_OnMessage(object sender, WebSocketSharp.MessageEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var index = e.Data.IndexOf("\u0000", StringComparison.Ordinal);
|
|
|
|
|
|
|
|
|
|
if (index <= -1)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var commonId = e.Data.Substring(0, index);
|
|
|
|
|
if (commonId != "notice") return;
|
|
|
|
|
var body = e.Data.Substring(index + 1);
|
|
|
|
|
var data = JsonConvert.DeserializeObject<AckNoticeData>(body);
|
|
|
|
|
if (data == null || string.IsNullOrEmpty(data.Id)) return;
|
|
|
|
|
this._websocket.Send("notice_ack\u0000" + data.Id);
|
|
|
|
|
OnMessageEvent?.Invoke(this, data);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"即时通讯API接收异常:{ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Thread _thread;
|
|
|
|
|
private void _websocket_OnOpen(object sender, System.EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
foreach (var v in this._channels)
|
|
|
|
|
{
|
|
|
|
|
this._websocket.Send($"subchannel\u0000{v}");//订阅通道
|
|
|
|
|
}
|
|
|
|
|
this.OnConnectedEvent?.Invoke(this, EventArgs.Empty);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"即时通讯API连接异常:{ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-01 06:18:07 +00:00
|
|
|
|
|
|
|
|
|
private int PingFailureCount { get; set; }
|
|
|
|
|
private string _pingId = Guid.NewGuid().ToString();
|
2022-09-20 03:10:29 +00:00
|
|
|
|
private void Ping()
|
|
|
|
|
{
|
2023-02-01 06:18:07 +00:00
|
|
|
|
var id = Guid.NewGuid().ToString();
|
|
|
|
|
_pingId = id;
|
|
|
|
|
while (_pingId == id)
|
2022-09-20 03:10:29 +00:00
|
|
|
|
{
|
|
|
|
|
Thread.Sleep(1000 * 10);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//测试ping是否正常
|
2023-02-01 06:18:07 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (_websocket == null)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (_websocket.ReadyState == WebSocketState.Open)
|
|
|
|
|
{
|
|
|
|
|
_websocket.Send("\u0001\u0002");
|
|
|
|
|
this.PingFailureCount = 0;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.PingFailureCount = this.PingFailureCount + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
// ignored
|
|
|
|
|
this.PingFailureCount = this.PingFailureCount + 1;
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
if (this.PingFailureCount > 5)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("心跳异常连接断开");
|
|
|
|
|
_websocket?.Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-20 03:10:29 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"即时通讯API Ping异常:{e.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// ReSharper disable once FunctionNeverReturns
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="key"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public string GetData(string key)
|
|
|
|
|
{
|
|
|
|
|
var http = new HttpHelper();
|
|
|
|
|
var html = http.GetHtml($"http://{this._host}/api/TransferData/Get?key={key}&rd={DateTime.Now.Ticks}").Html;
|
|
|
|
|
var rest = JObject.Parse(html);
|
|
|
|
|
//if (!(rest["Ok"] ?? false).Value<bool>() throw new Exception(html);
|
|
|
|
|
//return (rest["Data"] ?? string.Empty).Value<string>();
|
|
|
|
|
|
|
|
|
|
//EventClient.OnEvent($"获取淘客域名数据", $"{html}");
|
|
|
|
|
|
|
|
|
|
if (!(rest["Ok"] ?? false).Value<bool>())
|
|
|
|
|
throw new Exception(html);
|
|
|
|
|
return (rest["Data"] ?? string.Empty).Value<string>();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|