199 lines
5.8 KiB
C#
199 lines
5.8 KiB
C#
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;
|
||
|
||
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);
|
||
|
||
/// <summary>
|
||
/// 连接
|
||
/// </summary>
|
||
public void Connect()
|
||
{
|
||
if (IsConnected)
|
||
{
|
||
_websocket.OnOpen -= _websocket_OnOpen;
|
||
_websocket.OnMessage -= _websocket_OnMessage;
|
||
_websocket?.Close();
|
||
}
|
||
|
||
_websocket = new WebSocket($"ws://{this._host}/api/push?id={DateTime.Now.Ticks}");
|
||
_websocket.OnOpen += _websocket_OnOpen;
|
||
_websocket.OnMessage += _websocket_OnMessage;
|
||
_websocket.Connect();
|
||
|
||
if (_thread == null)
|
||
{
|
||
_thread = new Thread(Ping)
|
||
{
|
||
IsBackground = true
|
||
};
|
||
_thread.Start();
|
||
}
|
||
}
|
||
|
||
/// <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}");
|
||
}
|
||
}
|
||
private void Ping()
|
||
{
|
||
while (true)
|
||
{
|
||
Thread.Sleep(1000 * 10);
|
||
try
|
||
{
|
||
//测试ping是否正常
|
||
if (this._websocket.Ping()) continue;
|
||
|
||
//断开自动重连
|
||
this.Connect();
|
||
}
|
||
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>();
|
||
|
||
}
|
||
|
||
}
|
||
} |