You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
6.8 KiB
204 lines
6.8 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
using ProtoCSStruct;
|
|
|
|
namespace Sog
|
|
{
|
|
public class WaitAckStructRequest
|
|
{
|
|
public long UniqueID;
|
|
public uint ServerID;
|
|
public bool TimeoutResend;
|
|
public int TimeoutMs;
|
|
public long SendTime;
|
|
public MessageData Message;
|
|
}
|
|
/// <summary>
|
|
/// 一定需要等待回应的消息发送器
|
|
/// 邮件之类需要严格处理逻辑的可以使用
|
|
/// </summary>
|
|
public class WaitAckStructRequestSender : Singleton<WaitAckStructRequestSender>
|
|
{
|
|
private ServerApp m_app;
|
|
private StructPacketSender m_packetSender;
|
|
private uint m_serverID;
|
|
|
|
private long m_lastUniqueID = 0;
|
|
private long m_lastTickTime = 0;
|
|
private int m_sendCountThisTick = 0; //频率控制
|
|
|
|
private Dictionary<long, WaitAckStructRequest> m_sendAllPacket = new Dictionary<long, WaitAckStructRequest>();
|
|
|
|
public void Init(StructPacketSender packetSender, uint serverID, ServerApp app)
|
|
{
|
|
m_packetSender = packetSender;
|
|
m_serverID = serverID;
|
|
m_app = app;
|
|
}
|
|
|
|
public long GeneratorUniqueID()
|
|
{
|
|
if(m_lastUniqueID == 0)
|
|
{
|
|
//每次重启服务器不会重复,全局唯一,且保证是正数
|
|
m_lastUniqueID = m_serverID;
|
|
m_lastUniqueID <<= 30;
|
|
m_lastUniqueID += (AppTime.GetNowSysMs() << 4);
|
|
}
|
|
|
|
m_lastUniqueID++;
|
|
|
|
return m_lastUniqueID;
|
|
}
|
|
|
|
public bool IsEmpty()
|
|
{
|
|
return m_sendAllPacket.Count == 0;
|
|
}
|
|
|
|
private void BeginSend<T>(long uniqueID, uint serverID, int iMsgID, ref T structMessage, long iObjectID, bool resend, int timeout)
|
|
where T : struct, IStructMessage<T>
|
|
{
|
|
WaitAckStructRequest waitAckOne = new WaitAckStructRequest();
|
|
waitAckOne.UniqueID = uniqueID;
|
|
waitAckOne.TimeoutResend = resend;
|
|
waitAckOne.TimeoutMs = timeout;
|
|
waitAckOne.SendTime = m_app.Time.GetTime();
|
|
waitAckOne.ServerID = serverID;
|
|
|
|
MessageData messageData = new MessageData();
|
|
messageData.Header.Type = iMsgID;
|
|
messageData.Header.ObjectID = iObjectID;
|
|
|
|
|
|
bool bRet = ProtoPackerFactory.Instance.GetProtoCSStructPacker().PackMessage(ref structMessage, ref messageData);
|
|
if (bRet == false)
|
|
{
|
|
//判断是不是sessionid,sessionid是个很大的数
|
|
if (Sog.Service.GateSessionID.IsGateSessionIDOrUserID(iObjectID))
|
|
{
|
|
TraceLog.Error("WaitAckStructRequestSender PackMessage error server {0} msgId {1} iID {2} message:{3}"
|
|
, ServerIDUtils.IDToString(serverID), iMsgID, iObjectID
|
|
, structMessage.GetName());
|
|
}
|
|
else
|
|
{
|
|
TraceLog.UserError(iObjectID, "WaitAckStructRequestSender PackMessage error server {0} msgId {1} iID {2} message:{3}"
|
|
, ServerIDUtils.IDToString(serverID), iMsgID, iObjectID
|
|
, structMessage.GetName());
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
waitAckOne.Message = messageData;
|
|
|
|
m_sendAllPacket.Add(uniqueID, waitAckOne);
|
|
|
|
m_packetSender.SendToServerByID(serverID, messageData.Clone());
|
|
|
|
/*
|
|
* 测试数据库会不会有相同uniqueID多份邮件
|
|
if (OSUtils.IsWindows())
|
|
{
|
|
m_packetSender.SendToServerByID(serverID, reqPacket);
|
|
}*/
|
|
}
|
|
|
|
public void BeginSendNeedResend<T>(long uniqueID, uint serverID, int iMsgID, ref T structMessage, long iObjectID, int timeout = 30*1000)
|
|
where T : struct, IStructMessage<T>
|
|
{
|
|
BeginSend(uniqueID, serverID, iMsgID, ref structMessage, iObjectID, true, timeout);
|
|
}
|
|
|
|
public void OnReceiveSuccess(long uniqueID)
|
|
{
|
|
WaitAckStructRequest waitAckOne;
|
|
if(m_sendAllPacket.TryGetValue(uniqueID,out waitAckOne))
|
|
{
|
|
TraceLog.Trace("WaitAckStructRequestSender.OnReceiveSuccess uniqueID {0} MsgID {1}, removed"
|
|
, uniqueID, waitAckOne.Message.Header.Type);
|
|
|
|
m_sendAllPacket.Remove(uniqueID);
|
|
waitAckOne.Message.FreeData();
|
|
}
|
|
else
|
|
{
|
|
TraceLog.Trace("WaitAckStructRequestSender.OnReceiveSuccess no uniqueID {0}", uniqueID);
|
|
}
|
|
}
|
|
|
|
public void Tick(long nowMs)
|
|
{
|
|
if(m_packetSender == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//1秒一次
|
|
if(nowMs - m_lastTickTime < 1000)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_sendCountThisTick = 0;
|
|
m_lastTickTime = nowMs;
|
|
|
|
List<long> deleteList = null;
|
|
|
|
foreach(var one in m_sendAllPacket.Values)
|
|
{
|
|
//timeout
|
|
if(nowMs - one.SendTime > one.TimeoutMs)
|
|
{
|
|
if(one.TimeoutResend)
|
|
{
|
|
one.SendTime = nowMs;
|
|
|
|
m_packetSender.SendToServerByID(one.ServerID, one.Message.Clone());
|
|
|
|
m_sendCountThisTick++;
|
|
|
|
//控制1秒最多100个请求,防止雪崩
|
|
if(m_sendCountThisTick > 100)
|
|
{
|
|
break;
|
|
}
|
|
TraceLog.Error("WaitAckStructRequestSender uniqueID {0} MsgID {1} timeout ,resend it, m_sendCountThisTick {2}"
|
|
, one.UniqueID, one.Message.Header.Type, m_sendCountThisTick);
|
|
}
|
|
else
|
|
{
|
|
TraceLog.Error("WaitAckStructRequestSender uniqueID {0} MsgID {1} timeout ,delete it"
|
|
, one.UniqueID, one.Message.Header.Type);
|
|
|
|
if(deleteList == null)
|
|
{
|
|
deleteList = new List<long>();
|
|
}
|
|
|
|
deleteList.Add(one.UniqueID);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if(deleteList != null)
|
|
{
|
|
foreach(long uniqueid in deleteList)
|
|
{
|
|
m_sendAllPacket[uniqueid].Message.FreeData();
|
|
m_sendAllPacket.Remove(uniqueid);
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool GetRequestByUniqueID(long uniqueId, out WaitAckStructRequest req)
|
|
{
|
|
return m_sendAllPacket.TryGetValue(uniqueId, out req);
|
|
}
|
|
}
|
|
}
|
|
|