old_flsystem/类库/Chat.Framework/WXSdk/IPAD/SocketClient.cs

454 lines
16 KiB
C#
Raw Normal View History

2022-09-20 03:10:29 +00:00

using Chat.Framework;
using Chat.Framework.WXSdk.Implement;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Chat.Framework.WXSdk.IPAD
{
/// <summary>
/// Socket管理
/// </summary>
public sealed class SocketClient
{
class SocketResult
{
public DateTime Time { get; set; }
public byte[] Data { get; set; }
}
public WeixinBase weixin;
public enum WXSocketClientError
{
connetedErr = 0,//连接错误
sendErr = 1,//发送错误
receiveErr = 2,//接受错误
};
internal Socket clientSocket;
internal DnsEndPoint hostEndPoint { get; set; }
public bool connected
{
get
{
if (this.clientSocket != null) return this.clientSocket.Connected;
return false;
}
}
Dictionary<int, SocketResult> mPackDic = new Dictionary<int, SocketResult>();
private object mPackDicLock = new object();
public Func<byte[], bool> NotifyCallback { get; set; }
int Seq = 0;
private byte[] packageData = null;
public void ClearPack()
{
lock (mPackDic)
{
var vas = mPackDic.ToList().Where(f => f.Value.Time < DateTime.Now.AddMinutes(-5));
foreach (var item in vas)
{
mPackDic.Remove(item.Key);
}
}
}
public Func<WXSocketClientError,SocketClient, bool> SocketExceptionCallback { get; set; }
public ManualResetEvent allDone = new ManualResetEvent(false);
public SocketClient(DnsEndPoint hostEndPoint, WeixinBase weixin)
{
this.weixin = weixin;
this.hostEndPoint = hostEndPoint;
CreateSocket();
}
//创建socket
public bool CreateSocket()
{
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSocket.SendTimeout = 10000;
SetXinTiao();
return true;
}
private object lock_login = new object();
public void BeginConnection()
{
try
{
this.allDone = new ManualResetEvent(false);
if (null == clientSocket)
{
CreateSocket();
}
//开始连接到服务器
clientSocket.BeginConnect(hostEndPoint, delegate
{
try
{
AsynRecive();
if (weixin.Status == Chat.Framework.WXSdk.WxStatus.线)
{
//var client = (this.weixin as WXClientImpl_IPAD);
//client.AsyncSyncMessage();
// if (!client.AsyncSyncMessage()) this.weixin.ResetConnection();
}
}
catch (Exception)
{ }
}, null);
Thread.Sleep(200);
// wait here until the connect finishes. The callback sets allDone.
//阻塞直到connected=true
//allDone.WaitOne(1000 * 5);
// Log("连接 WeChat 成功!");
LogHelper.GetSingleObj().Info("Wechat Connect", $"{weixin.WeixinHao}-{hostEndPoint}-连接成功!!!!");
}
catch (Exception ex)
{
LogHelper.GetSingleObj().Error("Wechat Connect", $"{weixin.WeixinHao}-{hostEndPoint}-连接失败!{ex.Message}");
// Log("连接 WeChat 失败!" + ex.Message);
//Log(new LogInfo(jobinfo.JobID, "调试", "创建wx服务器连接失败详情" + ex.Message + Environment.NewLine + ex.StackTrace, 3));
//Log(new LogInfo(jobinfo.JobID, "错误", "创建wx服务器连接异常", 1));
}
}
//异步连接
public bool Connect()
{
lock (lock_login)
{
this.Disconnect();
BeginConnection();
Thread.Sleep(1000);
}
return connected;
}
//断开socket
public void Disconnect()
{
try
{
if (clientSocket != null && clientSocket.Connected)
{
LogHelper.GetSingleObj().Info("Wechat Disconnect", $"{weixin.WeixinHao}-{hostEndPoint}-关闭");
}
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Disconnect(true);
clientSocket.Close();
clientSocket.Dispose();
clientSocket = null;
allDone.Dispose();
}
catch (Exception)
{ }
}
///// 设置socket心跳
private void SetXinTiao()
{
//byte[] inValue = new byte[] { 1, 0, 0, 0, 0x20, 0x4e, 0, 0, 0xd0, 0x07, 0, 0 };// 首次探测时间20 秒, 间隔侦测时间2 秒
byte[] inValue = new byte[] { 1, 0, 0, 0, 0x88, 0x13, 0, 0, 0xd0, 0x07, 0, 0 };// 首次探测时间5 秒, 间隔侦测时间2 秒
clientSocket.IOControl(IOControlCode.KeepAliveValues, inValue, null);
}
/// <summary>
/// 发送vx socket消息
/// </summary>
/// <param name="socket"></param>
/// <param name="message"></param>
public void AsynSend(byte[] _SendBuff)
{
try
{
int times = 0;
while (!connected && times < 5)
{
// Log(new LogInfo(jobinfo.JobID, "调试", , 3));
// LogHelper.GetSingleObj().Error("Wechat AsynSend", $"{weixin.WeixinHao}-{hostEndPoint}- 等待连接!");
Thread.Sleep(2000);
times++;
}
if (!connected)
{
LogHelper.GetSingleObj().Error("Wechat AsynSend", $"{weixin.WeixinHao}-{hostEndPoint}- 等待连接!");
if (null != SocketExceptionCallback)
{
SocketExceptionCallback(WXSocketClientError.connetedErr,this);
}
return;
//Log("wx服务器连接失败请尝试重启工号");
// this.Connect();
}
byte[] SendBuff = _SendBuff;
var temp = Encoding.UTF8.GetString(SendBuff);
clientSocket.BeginSend(SendBuff, 0, SendBuff.Length, SocketFlags.None, asyncResult =>
{
try
{
//完成发送消息
int length = clientSocket.EndSend(asyncResult);
LogHelper.GetSingleObj().Info("Wechat AsynSend", $"{weixin.WeixinHao}-{hostEndPoint}-已发送{length}字节!");
}
catch (Exception)
{ }
}, null);
}
catch (Exception ex)
{
//Log ("wx服务器接收数据异常详情" + ex.Message + Environment.NewLine + ex.StackTrace) ;
LogHelper.GetSingleObj().Error("Wechat AsynSend", $"{weixin.WeixinHao}-{hostEndPoint}- 发送失败!{ex.Message}");
//微信socket异常问题
if (null != SocketExceptionCallback)
{
if (ex.Message.Contains("主机中的软件中止了一个已建立的连接。"))
SocketExceptionCallback(WXSocketClientError.connetedErr,this);
else SocketExceptionCallback(WXSocketClientError.sendErr,this);
}
}
}
/// <summary>
/// 通过seq取微信服务器返回的socket包数据
/// </summary>
/// <param name="Seq"></param>
/// <returns></returns>
public byte[] GetBuffBySeq(int Seq)
{
lock (mPackDicLock)
{
//Thread.Sleep(10);
byte[] buf = null;
try
{
if (mPackDic.ContainsKey(Seq))
{
buf = mPackDic[Seq].Data;
mPackDic.Remove(Seq);
return buf;
}
}
catch (Exception ee)
{
LogHelper.GetSingleObj().Error("Wechat GetBuffBySeq", $"{weixin.WeixinHao}-{hostEndPoint}- 获取超时!{ee.Message}");
}
return buf;
}
}
/// <summary>
/// 接收微信socket返回的数据
/// </summary>
/// <param name="socket"></param>
private void AsynRecive()
{
Thread.Sleep(50);
if (connected == false || clientSocket == null)
return;
//byte[] data = new byte[0x20000];
byte[] data = new byte[150000];
try
{
//开始接收数据
clientSocket.BeginReceive(data, 0, data.Length, SocketFlags.None,
asyncResult =>
{
if (connected == false || clientSocket == null)
{
return;
}
try
{
//本次接收的数据长度
int nowReceiveLenth = clientSocket.EndReceive(asyncResult);
//建立起连接后 若长时间不发送数据 wx会立马关闭socket
if (nowReceiveLenth == 0)
{
//vx socket 服务端关闭了连接需要重连socket
//if (clientSocket.Connected)//上次socket的状态
//{
//Log("wxsocket服务端关闭了连接将尝试新建连接");
//微信socket异常问题
if (null != SocketExceptionCallback)
{
SocketExceptionCallback(WXSocketClientError.receiveErr,this);
}
//}
return;
}
byte[] new_data = new byte[nowReceiveLenth];
Buffer.BlockCopy(data, 0, new_data, 0, nowReceiveLenth);
LogHelper.GetSingleObj().Info("Wechat AsynRecive", $"{weixin.WeixinHao}-{hostEndPoint}-{data.Length}");
DePack(new_data);
AsynRecive();
}
catch (Exception ex)
{
//LogHelper.GetSingleObj().Error("Wechat AsynRecive1", ex.Message);
LogHelper.GetSingleObj().Error("Wechat AsynRecive1", $"{weixin.WeixinHao}-{hostEndPoint}- { ex.Message}");
// Log("解析wx数据异常详情" + ee.Message + Environment.NewLine + ee.StackTrace);
// Log(new LogInfo(jobinfo.JobID, "调试", "wxsocket服务端关闭了连接将尝试新建连接", 3));
//微信socket异常问题
if (null != SocketExceptionCallback)
{
SocketExceptionCallback(WXSocketClientError.receiveErr,this);
}
}
}, null);
}
catch (Exception ex)
{
// Log("连接被wx服务器关闭接收数据失败。异常详情" + ex.Message + Environment.NewLine + ex.StackTrace);
// LogHelper.GetSingleObj().Error("Wechat AsynRecive2", ex.Message);
LogHelper.GetSingleObj().Error("Wechat AsynRecive2", $"{weixin.WeixinHao}-{hostEndPoint}- { ex.Message}");
//微信socket异常问题
if (null != SocketExceptionCallback) SocketExceptionCallback(WXSocketClientError.receiveErr,this);
}
//finally
//{
//}
}
//分包
public bool DePack(byte[] bys)
{
bool result = false;
int x = bys.Length;
if (packageData != null)
{
byte[] temp = new byte[packageData.Length + x];
Buffer.BlockCopy(packageData, 0, temp, 0, packageData.Length);
Buffer.BlockCopy(bys, 0, temp, packageData.Length, x);
packageData = temp;
}
else
{
packageData = new byte[x];
Buffer.BlockCopy(bys, 0, packageData, 0, x);
}
while (packageData != null && packageData.Length > 16)
{
int newPackageLength = WXClientTool.ReadInt(packageData, 0);
if (newPackageLength <= 0 || newPackageLength > 8000000)
{
LogHelper.GetSingleObj().Error("Wechat DePack", "长度不合法");
packageData = null;
}
else if (newPackageLength <= packageData.Length)
{
byte[] newPackage = new byte[newPackageLength];
Buffer.BlockCopy(packageData, 0, newPackage, 0, newPackageLength);
if (newPackageLength < packageData.Length)
{
byte[] temData = new byte[packageData.Length - newPackageLength];
Buffer.BlockCopy(packageData, newPackageLength, temData, 0, packageData.Length - newPackageLength);
packageData = temData;
}
else
{
packageData = null;
}
HandlePackage(newPackage);
}
else
{
break;
}
}
return result;
}
//解析包
public void HandlePackage(byte[] bys)
{
if (bys.Length == 20 && bys[3] == 20 && bys[5] == 16 && bys[7] == 1)
{
// 有新消息就会接受到此包
SaveBufferToPackDic(bys);
return;
}
else
{
if (bys.Length >= 16 && bys[16] != (byte)191
&& !(bys[3] == 58 && bys[5] == 16 && bys[7] == 1 && bys.Length == 58)
&& !(bys[3] == 47 && bys[5] == 16 && bys[7] == 1 && bys.Length == 47))
{
return;
}
SaveBufferToPackDic(bys);
}
}
//保存数据到mPackDic
public void SaveBufferToPackDic(byte[] bys)
{
lock (mPackDicLock)
{
Seq = WXClientTool.ReadInt(bys, 12);
if (Seq == 0)
{
byte[] buffers = new byte[bys.Length];
Buffer.BlockCopy(bys, 0, buffers, 0, bys.Length);
int cmd = WXClientTool.ReadInt(buffers, 8);
int selector = WXClientTool.ReadInt(buffers, 16);
LogHelper.GetSingleObj().Info("Wechat SaveBufferToPackDic", $"{weixin.WeixinHao}-{hostEndPoint}-收到{buffers.Length}字节!");
if (cmd == 318 && NotifyCallback != null)
{
NotifyCallback(buffers);
}
if (cmd == 24 && NotifyCallback != null)
{
NotifyCallback(buffers);
}
if (cmd != 24 && cmd != 318)
{
}
}
else
{
byte[] buffers = new byte[bys.Length];
Buffer.BlockCopy(bys, 0, buffers, 0, bys.Length);
mPackDic[Seq] = new SocketResult() { Data = buffers, Time = DateTime.Now };
Seq = 0;
}
}
}
}
}