338 lines
9.7 KiB
C#
338 lines
9.7 KiB
C#
using Chat.Framework.WXSdk.Implement;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using SuperSocket.ClientEngine;
|
|
using SuperSocket.ProtoBase;
|
|
|
|
namespace Chat.Framework.WXSdk.IPAD
|
|
{
|
|
public class SocketTest
|
|
{
|
|
|
|
DnsEndPoint hostEndPoint;
|
|
public SocketTest(DnsEndPoint hostEndPoint, WXClientImpl_IPAD weixin)
|
|
{
|
|
this.weixin = weixin;
|
|
this.hostEndPoint = hostEndPoint;
|
|
|
|
|
|
}
|
|
public bool connected
|
|
{
|
|
get
|
|
{
|
|
return Client != null ? Client.IsConnected : false;
|
|
}
|
|
}
|
|
private EasyClient Client;
|
|
public bool Connect()
|
|
{
|
|
this.Disconnect();
|
|
|
|
Client = new EasyClient();
|
|
Client.Initialize(new ProtobufReceiveFilter(), (request) => {
|
|
Client_OnReceive(request.buffer);
|
|
});
|
|
Client.Error += Client_Error;
|
|
Client.Closed += Client_Closed;
|
|
var _connected = Client.ConnectAsync(this.hostEndPoint);
|
|
return _connected.Result;
|
|
|
|
}
|
|
|
|
private void Client_Closed(object sender, EventArgs e)
|
|
{
|
|
LogHelper.GetSingleObj().Error("Socket_Error", $"{weixin.WeixinHao}-Socket Close");
|
|
}
|
|
|
|
private void Client_Error(object sender, ErrorEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
|
|
LogHelper.GetSingleObj().Error("Socket_Error", $"{weixin.WeixinHao}-Socket Error");
|
|
if (this.weixin.Status == WxStatus.在线)
|
|
{
|
|
if (this.Connect())
|
|
{
|
|
this.weixin.AsyncSyncMessage();
|
|
}
|
|
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
|
|
}
|
|
|
|
private void Client_OnReceive(byte[] obj)
|
|
{
|
|
//Console.WriteLine($"Push接收长度[{obj.Length}] {random.Next(1, 9999)}");
|
|
try
|
|
{
|
|
DePack(obj);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
public void AsynSend(byte[] data, string text = "")
|
|
{
|
|
try
|
|
{
|
|
Client.Send(data);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
|
|
}
|
|
|
|
public void Disconnect()
|
|
{
|
|
try
|
|
{
|
|
if (this.Client != null)
|
|
{
|
|
this.Client.Close();
|
|
this.Client = null;
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <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}- 获取超时!{ee.Message}");
|
|
}
|
|
return buf;
|
|
}
|
|
}
|
|
|
|
|
|
private object mPackDicLock = new object();
|
|
private byte[] packageData = null;
|
|
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);
|
|
}
|
|
}
|
|
class SocketResult
|
|
{
|
|
public DateTime Time { get; set; }
|
|
public byte[] Data { get; set; }
|
|
}
|
|
Dictionary<int, SocketResult> mPackDic = new Dictionary<int, SocketResult>();
|
|
public WXClientImpl_IPAD weixin;
|
|
public Func<byte[], bool> NotifyCallback { get; set; }
|
|
// int Seq = 0;
|
|
//保存数据到mPackDic
|
|
public void SaveBufferToPackDic(byte[] bys)
|
|
{
|
|
lock (mPackDicLock)
|
|
{
|
|
var 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}-收到{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;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public class ProtobufPackageInfo : IPackageInfo {
|
|
public byte[] buffer { get; set; }
|
|
}
|
|
public class ProtobufReceiveFilter : IReceiveFilter<ProtobufPackageInfo>
|
|
{
|
|
public IReceiveFilter<ProtobufPackageInfo> NextReceiveFilter { get; protected set; }
|
|
|
|
public FilterState State => FilterState.Normal;
|
|
|
|
public ProtobufPackageInfo Filter(BufferList data, out int rest)
|
|
{
|
|
rest = 0;
|
|
var list = data.Last;
|
|
byte[] buffer = new byte[list.Count];
|
|
Array.Copy(list.Array, buffer, list.Count);
|
|
return new ProtobufPackageInfo() { buffer = buffer };
|
|
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NextReceiveFilter = null;
|
|
}
|
|
}
|
|
public class MyReceiveFilter : SuperSocket.ProtoBase.IReceiveFilter<BufferedPackageInfo>
|
|
{
|
|
public IReceiveFilter<BufferedPackageInfo> NextReceiveFilter { get; protected set; }
|
|
|
|
public FilterState State => FilterState.Normal;
|
|
|
|
public BufferedPackageInfo Filter(BufferList data, out int rest)
|
|
{
|
|
|
|
rest=0;
|
|
var list = data.Last;
|
|
byte[] buffer = new byte[list.Count];
|
|
Array.Copy(list.Array, buffer, list.Count);
|
|
|
|
return new BufferedPackageInfo("wx", new List<System.ArraySegment<byte>>() {
|
|
new ArraySegment<byte>(buffer)
|
|
});
|
|
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
NextReceiveFilter = null;
|
|
}
|
|
}
|
|
|
|
}
|