369 lines
13 KiB
C#
369 lines
13 KiB
C#
|
using CsharpHttpHelper;
|
|||
|
using PCRobot.Pack;
|
|||
|
using PCRobot.PCWechat;
|
|||
|
using PCRobot.Utils;
|
|||
|
using SuperSocket.ClientEngine;
|
|||
|
using SuperSocket.ProtoBase;
|
|||
|
using System;
|
|||
|
using System.Linq;
|
|||
|
using System.Net;
|
|||
|
using System.Text;
|
|||
|
using System.Text.RegularExpressions;
|
|||
|
using System.Threading;
|
|||
|
|
|||
|
namespace PCRobot
|
|||
|
{
|
|||
|
public class EasySoc
|
|||
|
{
|
|||
|
#region 字段信息
|
|||
|
static EasySoc _soc;
|
|||
|
|
|||
|
public EasyClient client;
|
|||
|
|
|||
|
public string key { get; private set; }
|
|||
|
|
|||
|
string ip;
|
|||
|
|
|||
|
int port;
|
|||
|
|
|||
|
public bool Stop { get; set; }
|
|||
|
|
|||
|
public bool IsConnected
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return client != null && client.IsConnected;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
readonly static object session_lock = new object();
|
|||
|
|
|||
|
IPEndPoint endPoint;
|
|||
|
|
|||
|
Action<string, string> ReceiveDataAction;
|
|||
|
|
|||
|
Action<string> StateAction;
|
|||
|
|
|||
|
Action<Exception> SocketErrorAction;
|
|||
|
|
|||
|
long i = 0;
|
|||
|
|
|||
|
//Thread threadConnection;
|
|||
|
|
|||
|
static bool lock_connection = false;
|
|||
|
#endregion
|
|||
|
|
|||
|
public static EasySoc GetSocket()
|
|||
|
{
|
|||
|
if (_soc == null) _soc = new EasySoc();
|
|||
|
return _soc;
|
|||
|
}
|
|||
|
private System.Threading.Timer timer = null;
|
|||
|
public EasySoc()
|
|||
|
{
|
|||
|
//timer = new Timer(new TimerCallback(timerCall), null, 0, 1000 * 5);
|
|||
|
var thread = new Thread(() =>
|
|||
|
{
|
|||
|
while (true)
|
|||
|
{
|
|||
|
Thread.Sleep(1000 * 5);
|
|||
|
timerCall(null);
|
|||
|
}
|
|||
|
});
|
|||
|
thread.IsBackground = true;
|
|||
|
thread.Start();
|
|||
|
//FluentScheduler.JobManager.AddJob(heartBeat, t =>
|
|||
|
//{
|
|||
|
// t.WithName("心跳").ToRunNow().AndEvery(5).Seconds();
|
|||
|
//});
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void timerCall(object state)
|
|||
|
{
|
|||
|
if (string.IsNullOrEmpty(ip) || string.IsNullOrEmpty(key) || port == 0) return;
|
|||
|
|
|||
|
//throw new NotImplementedException();
|
|||
|
var sb = new StringBuilder();
|
|||
|
try
|
|||
|
{
|
|||
|
sb.AppendLine("AAA");
|
|||
|
if (Stop)
|
|||
|
{
|
|||
|
sb.AppendLine("BBB");
|
|||
|
if (IsConnected) Close();
|
|||
|
sb.AppendLine("ccc");
|
|||
|
StateAction?.Invoke($"您已断开与服务器{ip}失联!");
|
|||
|
return;
|
|||
|
}
|
|||
|
sb.AppendLine("DDD");
|
|||
|
if (!IsConnected)
|
|||
|
{
|
|||
|
sb.AppendLine("EEE");
|
|||
|
StateAction?.Invoke($"与服务器{ip}失联,重连中...");
|
|||
|
|
|||
|
if (WechatClient.IsLog)
|
|||
|
{
|
|||
|
sb.AppendLine("FFF");
|
|||
|
LogHelper.GetSingleObj().Info("失联", $"与服务器{ip}失联,重连中...");
|
|||
|
}
|
|||
|
Connection(ip, port, ReceiveDataAction, SocketErrorAction, key, StateAction);
|
|||
|
sb.AppendLine("GGG");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
sb.AppendLine("HHH");
|
|||
|
i++;
|
|||
|
//Console.WriteLine($"第{i}次测试,key={this.key}");
|
|||
|
|
|||
|
if (i == 1 || i % 6 == 0)
|
|||
|
{
|
|||
|
sb.AppendLine("TTT");
|
|||
|
Send(new CommonResult()
|
|||
|
{
|
|||
|
Cmd = PCRobotCMD.heartBreak,
|
|||
|
RobotType = RobotType.客户端系统,
|
|||
|
RobotUsername = string.Empty,
|
|||
|
RobotUsernick = "测试-nick",
|
|||
|
Data = Common.GetDevice()
|
|||
|
});
|
|||
|
Thread.Sleep(50);
|
|||
|
sb.AppendLine("LLL");
|
|||
|
var robots = WechatClient.Users.Values.ToList();
|
|||
|
foreach (var item in robots)
|
|||
|
{
|
|||
|
sb.AppendLine("MMM");
|
|||
|
if (item.HeartBreakTime.AddMinutes(6) > DateTime.Now)
|
|||
|
{
|
|||
|
var msg = new WechatStatus()
|
|||
|
{
|
|||
|
Cmd = item.Type == WechatType.Xiaoxie_QY ? PCRobotCMD.offline_workWeChat : PCRobotCMD.offline,
|
|||
|
RobotUsername = item.Wxid,
|
|||
|
RobotUsernick = item.Nickname,//Regex.Replace(item.Nickname, @"\s", "", RegexOptions.IgnoreCase),
|
|||
|
RobotType = item.Type == WechatType.Xiaoxie_QY ? RobotType.客户端企业微信 : RobotType.客户端微信,
|
|||
|
Status = Status.在线,
|
|||
|
Uin = item.Uin,
|
|||
|
Device = Common.GetDevice()
|
|||
|
};
|
|||
|
Send(msg);
|
|||
|
Thread.Sleep(50);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
sb.AppendLine("NNN");
|
|||
|
item.HeartBreakTime = DateTime.Now;
|
|||
|
Close();
|
|||
|
if (!IsConnected) Connection(ip, port, ReceiveDataAction, SocketErrorAction, key, StateAction);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
sb.AppendLine("ZZZ");
|
|||
|
StateAction?.Invoke($"与服务器: {ip} 连接成功.");
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("心跳包异常1", $"{ex.Message}");
|
|||
|
StateAction?.Invoke($"心跳包异常: {ex.Message} {ex.StackTrace} +{sb.ToString()}");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Send(BaseMsg msg)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (IsConnected)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
msg.Key = this.key;
|
|||
|
var json = HttpHelper.ObjectToJson(msg);
|
|||
|
var data = PackTool.CompressString(json);
|
|||
|
var send = msg.Cmd + " " + data + "\r\n";
|
|||
|
var data_bytes = Encoding.UTF8.GetBytes(send);
|
|||
|
if (WechatClient.IsDebug) LogHelper.GetSingleObj().Debug("往服务器发送", $"{msg.Cmd} - {json} - {data.Length}");
|
|||
|
|
|||
|
//var senddata = new byte[_receiveBufferSize];
|
|||
|
//for (int i = 0; i < data_bytes.Length; i++)
|
|||
|
//{
|
|||
|
// senddata[i] = data_bytes[i];
|
|||
|
//}
|
|||
|
|
|||
|
client.Send(data_bytes);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
StateAction?.Invoke($"发送消息失败: {ex.Message}");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("Send ERROR", $"{ex.Message}");
|
|||
|
LogHelper.GetSingleObj().Error("Send ERROR:", $"{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static int _receiveBufferSize = 1024 * 1024 * 10;
|
|||
|
public void Connection(string ip, int port, Action<string, string> receiveDataAction, Action<Exception> socketErrorAction, string key, Action<string> stateAction)
|
|||
|
{
|
|||
|
if (Stop) return;
|
|||
|
if (lock_connection) return;
|
|||
|
if (key.Length != 16) throw new Exception("秘钥必须 == 16位!");
|
|||
|
try
|
|||
|
{
|
|||
|
lock_connection = true;
|
|||
|
if (this.IsConnected) this.Close();
|
|||
|
//Console.WriteLine("连接中...");
|
|||
|
this.ip = ip;
|
|||
|
this.port = port;
|
|||
|
if (receiveDataAction != null)
|
|||
|
{
|
|||
|
this.ReceiveDataAction = receiveDataAction;
|
|||
|
}
|
|||
|
if (stateAction != null)
|
|||
|
{
|
|||
|
this.StateAction = stateAction;
|
|||
|
}
|
|||
|
if (socketErrorAction != null)
|
|||
|
{
|
|||
|
this.SocketErrorAction = socketErrorAction;
|
|||
|
}
|
|||
|
|
|||
|
this.key = key.Substring(0, 16);
|
|||
|
this.endPoint = new IPEndPoint(IPAddress.Parse(ip), port);
|
|||
|
lock (session_lock)
|
|||
|
{
|
|||
|
client = new EasyClient();
|
|||
|
client.Initialize(new MyReceiveFilter(), clientRcv);
|
|||
|
client.ReceiveBufferSize = _receiveBufferSize;
|
|||
|
|
|||
|
|
|||
|
//LogHelper.GetSingleObj().Info("", "client.ReceiveBufferSize = " + client.ReceiveBufferSize);
|
|||
|
|
|||
|
//client.DataReceived += Client_DataReceived;
|
|||
|
|
|||
|
client.Connected += Client_Connected;
|
|||
|
client.Closed += Client_Closed;
|
|||
|
client.Error += Client_Error;
|
|||
|
var rst = client.ConnectAsync(endPoint).Result;
|
|||
|
Thread.Sleep(500);
|
|||
|
if (!client.IsConnected)
|
|||
|
{
|
|||
|
rst = client.ConnectAsync(endPoint).Result;
|
|||
|
if (!client.IsConnected)
|
|||
|
throw new Exception("连接服务器失败,请检查是否填写正确!");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("断开", $"连接服务器失败:{ex.Message}");
|
|||
|
StateAction?.Invoke($"连接服务器失败:{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
lock_connection = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void clientRcv(StringPackageInfo obj)
|
|||
|
{
|
|||
|
if (WechatClient.IsDebug)
|
|||
|
LogHelper.GetSingleObj().Debug("", $"收到服务器消息:{obj.Key} - {obj.Body}");
|
|||
|
|
|||
|
if (obj.Key.ToLower().Trim().StartsWith("offline".ToLower()))
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
var json = HttpExtend.JsonToDictionary(obj.Body);
|
|||
|
if (json != null)
|
|||
|
{
|
|||
|
var client = WechatClient.Users.Values.ToList().FirstOrDefault(f => f.Wxid == json["RobotUsername"].ToString());
|
|||
|
if (client != null)
|
|||
|
client.HeartBreakTime = DateTime.Now;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
var text = PackTool.DecompressString(obj.Body);
|
|||
|
var json1 = HttpExtend.JsonToDictionary(text);
|
|||
|
if (json1 != null)
|
|||
|
{
|
|||
|
var client = WechatClient.Users.Values.ToList().FirstOrDefault(f => f.Wxid == json1["RobotUsername"].ToString());
|
|||
|
if (client != null)
|
|||
|
client.HeartBreakTime = DateTime.Now;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{ }
|
|||
|
return;
|
|||
|
}
|
|||
|
//Console.WriteLine(obj.Body);
|
|||
|
//ReceiveDataAction.BeginInvoke(Encoding.UTF8.GetString(new_data), null, null);
|
|||
|
ReceiveDataAction.BeginInvoke(obj.Key, obj.Body, null, null);
|
|||
|
}
|
|||
|
|
|||
|
public void Close(bool isQuit = false)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
lock (session_lock)
|
|||
|
{
|
|||
|
if (client != null)
|
|||
|
{
|
|||
|
if (isQuit)
|
|||
|
{
|
|||
|
FluentScheduler.JobManager.RemoveJob("心跳");
|
|||
|
}
|
|||
|
|
|||
|
//client.DataReceived -= Client_DataReceived;
|
|||
|
client.Connected -= Client_Connected;
|
|||
|
client.Closed -= Client_Closed;
|
|||
|
client.Error -= Client_Error;
|
|||
|
client.Close();
|
|||
|
client = null;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("Close ERROR:", $"{ex.Message}");
|
|||
|
|
|||
|
LogHelper.GetSingleObj().Error("Close ERROR:", $"{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void Client_Error(object sender, ErrorEventArgs e)
|
|||
|
{
|
|||
|
if (SocketErrorAction != null)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("Client_Error", $"{e.Exception.Message}");
|
|||
|
SocketErrorAction(e.Exception);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void Client_Closed(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("断开", $"与服务器{ip},{e} - 连接断开!!");
|
|||
|
StateAction?.Invoke($"与服务器{ip}连接断开!");
|
|||
|
}
|
|||
|
|
|||
|
private void Client_Connected(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
{
|
|||
|
LogHelper.GetSingleObj().Info("连接成功", $"与服务器{ip}连接成功!");
|
|||
|
}
|
|||
|
StateAction?.Invoke($"与服务器{ip}连接成功!");
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|