326 lines
12 KiB
C#
326 lines
12 KiB
C#
|
using CsharpHttpHelper;
|
|||
|
using PCRobot.Pack;
|
|||
|
using PCRobot.PCWechat;
|
|||
|
using SuperSocket.ClientEngine;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using System.Net;
|
|||
|
using System.Text;
|
|||
|
using System.Threading;
|
|||
|
using System.Threading.Tasks;
|
|||
|
|
|||
|
namespace PCRobot
|
|||
|
{
|
|||
|
public class EasySoc
|
|||
|
{
|
|||
|
private static EasySoc _socket;
|
|||
|
public static EasySoc GetSocket()
|
|||
|
{
|
|||
|
if (_socket == null) _socket = new EasySoc();
|
|||
|
return _socket;
|
|||
|
}
|
|||
|
public EasySoc()
|
|||
|
{
|
|||
|
timer = new System.Threading.Timer(new TimerCallback(timerCall), null, 0, 1000 * 5);
|
|||
|
}
|
|||
|
public bool IsConnected
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (client != null && client.IsConnected) return true;
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
public bool Stop { get; set; }
|
|||
|
AsyncTcpSession client;
|
|||
|
//EasyClient client;
|
|||
|
|
|||
|
private readonly static object session_lock = new object();
|
|||
|
|
|||
|
public void Close(bool isQuit = false)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
lock (session_lock)
|
|||
|
{
|
|||
|
if (client != null)
|
|||
|
{
|
|||
|
if (isQuit)
|
|||
|
timer.Dispose();
|
|||
|
|
|||
|
//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}");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
IPEndPoint endPoint;
|
|||
|
private Action<string> ReceiveDataAction;
|
|||
|
|
|||
|
private Action<string> StateAction;
|
|||
|
|
|||
|
private Action<Exception> SocketErrorAction;
|
|||
|
|
|||
|
public string key { get; private set; }
|
|||
|
private string ip;
|
|||
|
private int port;
|
|||
|
private System.Threading.Timer timer = null;
|
|||
|
private static bool lock_connection = false;
|
|||
|
public void Connection(string ip, int port, Action<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;
|
|||
|
this.ReceiveDataAction = ReceiveDataAction;
|
|||
|
this.StateAction = StateAction;
|
|||
|
this.SocketErrorAction = SocketErrorAction;
|
|||
|
this.key = key.Substring(0, 16);
|
|||
|
this.endPoint = new IPEndPoint(IPAddress.Parse(ip), port);
|
|||
|
lock (session_lock)
|
|||
|
{
|
|||
|
client = new AsyncTcpSession();
|
|||
|
client.ReceiveBufferSize = 10 * 1024;
|
|||
|
client.DataReceived += Client_DataReceived;
|
|||
|
client.Connected += Client_Connected;
|
|||
|
client.Closed += Client_Closed;
|
|||
|
client.Error += Client_Error;
|
|||
|
client.Connect(endPoint);
|
|||
|
Thread.Sleep(500);
|
|||
|
if (!client.IsConnected)
|
|||
|
{
|
|||
|
client.Connect(endPoint);
|
|||
|
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 Client_Closed(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("断开", $"与服务器{ip}连接断开!!");
|
|||
|
StateAction?.Invoke($"与服务器{ip}连接断开!");
|
|||
|
}
|
|||
|
|
|||
|
private void Client_Connected(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("连接成功", $"与服务器{ip}连接成功!");
|
|||
|
StateAction?.Invoke($"与服务器{ip}连接成功!");
|
|||
|
}
|
|||
|
private long i = 0;
|
|||
|
private void timerCall(object state)
|
|||
|
{
|
|||
|
if (string.IsNullOrEmpty(ip) || string.IsNullOrEmpty(key) || port == 0) return;
|
|||
|
//throw new NotImplementedException();
|
|||
|
try
|
|||
|
{
|
|||
|
if (Stop)
|
|||
|
{
|
|||
|
if (IsConnected) Close();
|
|||
|
}
|
|||
|
if (!IsConnected)
|
|||
|
{
|
|||
|
if (Stop) StateAction?.Invoke($"您已断开与服务器{ip}失联!");
|
|||
|
else
|
|||
|
{
|
|||
|
StateAction?.Invoke($"与服务器{ip}失联,重连中...");
|
|||
|
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("失联", $"与服务器{ip}失联,重连中...");
|
|||
|
Connection(ip, port, ReceiveDataAction, SocketErrorAction, key, StateAction);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
i++;
|
|||
|
//Console.WriteLine($"第{i}次测试,key={this.key}");
|
|||
|
|
|||
|
if (i == 1 || i % 5 == 0)
|
|||
|
{
|
|||
|
//Send(new BaseMsg()
|
|||
|
//{
|
|||
|
// Cmd = PCRobotCMD.heartBreak,
|
|||
|
// RobotType = RobotType.客户端微信,
|
|||
|
// RobotUsername = "测试",
|
|||
|
// RobotUsernick = "测试-可以随时删除"
|
|||
|
//});
|
|||
|
//Send();
|
|||
|
//var wxs = WinForm.nms.ToList();
|
|||
|
|
|||
|
var robots = PCWechat.WechatClient.Users.Values.ToList();
|
|||
|
foreach (var item in robots)
|
|||
|
{
|
|||
|
//var msg = new BaseMsg()
|
|||
|
//{
|
|||
|
// Cmd = PCRobotCMD.heartBreak,
|
|||
|
// RobotType = RobotType.客户端系统,
|
|||
|
// RobotUsername = item.Wxid,
|
|||
|
// RobotUsernick = item.Nickname
|
|||
|
//};
|
|||
|
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,
|
|||
|
RobotType = item.Type == WechatType.Xiaoxie_QY ? RobotType.客户端企业微信 : RobotType.客户端微信,
|
|||
|
Status = Status.在线,
|
|||
|
Uin = item.Uin
|
|||
|
};
|
|||
|
Send(msg);
|
|||
|
Thread.Sleep(50);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
item.HeartBreakTime = DateTime.Now;
|
|||
|
Close();
|
|||
|
if (!IsConnected) Connection(ip, port, ReceiveDataAction, SocketErrorAction, key, StateAction);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
StateAction?.Invoke($"与服务器: {ip} 连接成功.");
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("心跳包异常1", $"{ex.Message}");
|
|||
|
StateAction?.Invoke($"心跳包异常: {ex.Message}");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
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_DataReceived(object sender, DataEventArgs e)
|
|||
|
{
|
|||
|
byte[] new_data = new byte[e.Length];
|
|||
|
Buffer.BlockCopy(e.Data, 0, new_data, 0, e.Length);
|
|||
|
|
|||
|
var data = Encoding.UTF8.GetString(new_data);
|
|||
|
var json = HttpHelper.JsonToObject<WechatStatus>(data) as WechatStatus;
|
|||
|
if (json == null)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//var client = WechatClient.Users.Values.ToList().FirstOrDefault(f => f.Wxid == json.RobotUsername && f.Type == (json.RobotType == RobotType.客户端企业微信 ? WechatType.Xiaoxie_QY : WechatType.Xiaoxie));
|
|||
|
var client = WechatClient.Users.Values.ToList().FirstOrDefault(f => f.Wxid == json.RobotUsername);
|
|||
|
if (client != null)
|
|||
|
client.HeartBreakTime = DateTime.Now;
|
|||
|
return;
|
|||
|
}
|
|||
|
Console.WriteLine(Encoding.UTF8.GetString(new_data));
|
|||
|
//ReceiveDataAction.BeginInvoke(Encoding.UTF8.GetString(new_data), null, null);
|
|||
|
ReceiveDataAction.BeginInvoke(data, null, null);
|
|||
|
}
|
|||
|
|
|||
|
int retry = 0;
|
|||
|
private Thread threadConnection;
|
|||
|
public void Send(BaseMsg msg)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (IsConnected)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
//秘钥
|
|||
|
//key = string.Empty;
|
|||
|
msg.Key = this.key;
|
|||
|
//Console.WriteLine("心跳测试:" + i + "," + msg.Key);
|
|||
|
var json = HttpHelper.ObjectToJson(msg);
|
|||
|
var data = PackTool.CompressString(json);
|
|||
|
//
|
|||
|
//if (!string.IsNullOrEmpty(key))
|
|||
|
//{
|
|||
|
// AESCryption aes = new AESCryption();
|
|||
|
// data = aes.AesEncrypt(data, key);
|
|||
|
//}
|
|||
|
|
|||
|
//data =HttpHelper.URLEncode(data);
|
|||
|
var send = msg.Cmd + " " + data + "\r\n";
|
|||
|
var data_bytes = Encoding.UTF8.GetBytes(send);
|
|||
|
client.Send(data_bytes,0,data_bytes.Length);
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
StateAction?.Invoke($"发送消息失败: {ex.Message}");
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
StateAction?.Invoke($"发送消息失败: 没有与服务器建立连接!");
|
|||
|
if (threadConnection == null || !threadConnection.IsAlive)
|
|||
|
{
|
|||
|
threadConnection = new Thread(new ThreadStart(delegate
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Thread.Sleep(5000);
|
|||
|
if (!IsConnected) Connection(ip, port, ReceiveDataAction, SocketErrorAction, key, StateAction);
|
|||
|
}
|
|||
|
catch (Exception)
|
|||
|
{
|
|||
|
}
|
|||
|
}));
|
|||
|
threadConnection.IsBackground = true;
|
|||
|
threadConnection.Start();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
if (WechatClient.IsLog)
|
|||
|
LogHelper.GetSingleObj().Info("Send ERROR", $"{ex.Message}");
|
|||
|
LogHelper.GetSingleObj().Error("Send ERROR:", $"{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|