//解析服务器返回的数据包,步骤如下: //1、把包头长度去掉 //2、CRC校验, //3、检查压缩标志,先校验CRC再解压,因为打包时的CRC就是压缩后的值 //4、使用异或算法得到真实包体 //5、通过解析协议编号,派发对应的委托 void Update() { while (true) { if (mReceiveCount <= 3) { mReceiveCount++; lock (mReceiveQueue) { if (mReceiveQueue.Count > 0) { byte[] buffer = mReceiveQueue.Dequeue(); //取一个服务器返回的未处理的数据包 byte[] dataBody = new byte[buffer.Length - 3]; //获取数据包包体,未解压(压缩标志+CRC一共3字节,包头部分在数据传过来的之前就处理掉了) bool isCompress = false; //压缩标志 ushort CRC = 0; //CRC校验码 ushort protoCode = 0; //协议编号 using (MemoryStreamUtil stream = new MemoryStreamUtil(buffer)) { isCompress = stream.ReadBool(); CRC = stream.ReadUShort(); stream.Read(dataBody, 0, dataBody.Length); } ushort newCRC = Crc16.CalculateCrc16(dataBody); if (CRC == newCRC) { if (isCompress) { dataBody = ZlibHelper.DeCompressBytes(dataBody); //解压 } dataBody = SecurityUtil.XorAlgorithm(dataBody); //解密 } else { Debug.Log("client:CRC验证失败!"); break; } //开始解析原始真实数据 byte[] protoContent = new byte[dataBody.Length - 2]; //协议内容,减去协议编号 using (MemoryStreamUtil stream = new MemoryStreamUtil(dataBody)) { protoCode = stream.ReadUShort(); //这里开始使用观察者派发协议 stream.Read(protoContent, 0, protoContent.Length); SocketDispatcher.Instance.Dispatch(protoCode, protoContent); } } else { break; } } } else { mReceiveCount = 0; break; } } }
/// <summary> /// 构造函数 /// </summary> /// <param name="path"></param> public GameDataTableParser(string path) { m_FieldNameDic = new Dictionary <string, int>(); //------------------ //第1步:读取文件 //------------------ /* 48课以后读取AB资源时使用新写法 * using (FileStream fs = new FileStream(path, FileMode.Open)) * { * buffer = new byte[fs.Length]; * fs.Read(buffer, 0, buffer.Length); * } */ byte[] buffer = LocalFileManager.Instance.GetBuffer(path); //------------------ //第2步:解压缩 //------------------ buffer = ZlibHelper.DeCompressBytes(buffer); //------------------ //第3步:xor解密 //43课以后将其移动到Leo_SecurityUtil中 //------------------ buffer = SecurityUtil.XorAlgorithm(buffer); //------------------ //第4步:解析数据到数组 //------------------ using (MemoryStreamUtil ms = new MemoryStreamUtil(buffer)) { m_Row = ms.ReadInt(); m_Column = ms.ReadInt(); m_GameData = new String[m_Row, m_Column]; m_FieldName = new string[m_Column]; for (int i = 0; i < m_Row; i++) { for (int j = 0; j < m_Column; j++) { string str = ms.ReadUTF8String(); if (i == 0) { //表示读取的是字段 m_FieldName[j] = str; m_FieldNameDic[str] = j; } else if (i > 2) { //表示读取的是内容 m_GameData[i, j] = str; } } } } }
public static Account_RoleInfoRespProto GetProto(byte[] buffer) { Account_RoleInfoRespProto proto = new Account_RoleInfoRespProto(); using (MemoryStreamUtil ms = new MemoryStreamUtil(buffer)) { proto.IsSuccess = ms.ReadBool(); if (proto.IsSuccess) { proto.RoldId = ms.ReadInt(); proto.RoleNickName = ms.ReadUTF8String(); proto.ClassId = (byte)ms.ReadByte(); proto.Level = ms.ReadInt(); proto.VIPLevel = ms.ReadInt(); proto.TotalRechargeGem = ms.ReadInt(); proto.Gem = ms.ReadInt(); proto.Gold = ms.ReadInt(); proto.CurrEnergy = ms.ReadInt(); proto.MaxEnergy = ms.ReadInt(); proto.Exp = ms.ReadInt(); proto.MaxHP = ms.ReadInt(); proto.MaxMP = ms.ReadInt(); proto.CurrHP = ms.ReadInt(); proto.CurrMP = ms.ReadInt(); proto.Attack = ms.ReadInt(); proto.Defense = ms.ReadInt(); proto.Hit = ms.ReadInt(); proto.Dodge = ms.ReadInt(); proto.Cri = ms.ReadInt(); proto.Res = ms.ReadInt(); proto.SumDPS = ms.ReadInt(); proto.LastPassGameQuestId = ms.ReadInt(); proto.LastInWorldMapId = ms.ReadInt(); proto.LastInWorldMapPos = ms.ReadUTF8String(); proto.Equip_Weapon = ms.ReadInt(); proto.Equip_Pants = ms.ReadInt(); proto.Equip_Clothes = ms.ReadInt(); proto.Equip_Belt = ms.ReadInt(); proto.Equip_Cuff = ms.ReadInt(); proto.Equip_Necklace = ms.ReadInt(); proto.Equip_Shoe = ms.ReadInt(); proto.Equip_Ring = ms.ReadInt(); proto.Equip_WeaponTableId = ms.ReadInt(); proto.Equip_PantsTableId = ms.ReadInt(); proto.Equip_ClothesTableId = ms.ReadInt(); proto.Equip_BeltTableId = ms.ReadInt(); proto.Equip_CuffTableId = ms.ReadInt(); proto.Equip_NecklaceTableId = ms.ReadInt(); proto.Equip_ShoeTableId = ms.ReadInt(); proto.Equip_RingTableId = ms.ReadInt(); } else { proto.MsgCode = ms.ReadInt(); } } return(proto); }
public int RoldId; //角色编号 public byte[] ToArray() { using (MemoryStreamUtil ms = new MemoryStreamUtil()) { ms.WriteUShort(ProtoCode); ms.WriteInt(RoldId); return(ms.ToArray()); } }
public int Equip_RingTableId; //穿戴戒指 public byte[] ToArray() { using (MemoryStreamUtil ms = new MemoryStreamUtil()) { ms.WriteUShort(ProtoCode); ms.WriteBool(IsSuccess); if (IsSuccess) { ms.WriteInt(RoldId); ms.WriteUTF8String(RoleNickName); ms.WriteByte(ClassId); ms.WriteInt(Level); ms.WriteInt(VIPLevel); ms.WriteInt(TotalRechargeGem); ms.WriteInt(Gem); ms.WriteInt(Gold); ms.WriteInt(CurrEnergy); ms.WriteInt(MaxEnergy); ms.WriteInt(Exp); ms.WriteInt(MaxHP); ms.WriteInt(MaxMP); ms.WriteInt(CurrHP); ms.WriteInt(CurrMP); ms.WriteInt(Attack); ms.WriteInt(Defense); ms.WriteInt(Hit); ms.WriteInt(Dodge); ms.WriteInt(Cri); ms.WriteInt(Res); ms.WriteInt(SumDPS); ms.WriteInt(LastPassGameQuestId); ms.WriteInt(LastInWorldMapId); ms.WriteUTF8String(LastInWorldMapPos); ms.WriteInt(Equip_Weapon); ms.WriteInt(Equip_Pants); ms.WriteInt(Equip_Clothes); ms.WriteInt(Equip_Belt); ms.WriteInt(Equip_Cuff); ms.WriteInt(Equip_Necklace); ms.WriteInt(Equip_Shoe); ms.WriteInt(Equip_Ring); ms.WriteInt(Equip_WeaponTableId); ms.WriteInt(Equip_PantsTableId); ms.WriteInt(Equip_ClothesTableId); ms.WriteInt(Equip_BeltTableId); ms.WriteInt(Equip_CuffTableId); ms.WriteInt(Equip_NecklaceTableId); ms.WriteInt(Equip_ShoeTableId); ms.WriteInt(Equip_RingTableId); } else { ms.WriteInt(MsgCode); } return(ms.ToArray()); } }
public int GameServerId; //区服ID public byte[] ToArray() { using (MemoryStreamUtil ms = new MemoryStreamUtil()) { ms.WriteUShort(ProtoCode); ms.WriteInt(AccountId); ms.WriteInt(GameServerId); return(ms.ToArray()); } }
public static Account_RoleInfoReqProto GetProto(byte[] buffer) { Account_RoleInfoReqProto proto = new Account_RoleInfoReqProto(); using (MemoryStreamUtil ms = new MemoryStreamUtil(buffer)) { proto.RoldId = ms.ReadInt(); } return(proto); }
public static Account_LoginGameServerReqProto GetProto(byte[] buffer) { Account_LoginGameServerReqProto proto = new Account_LoginGameServerReqProto(); using (MemoryStreamUtil ms = new MemoryStreamUtil(buffer)) { proto.AccountId = ms.ReadInt(); proto.GameServerId = ms.ReadInt(); } return(proto); }
public static Account_EnterGameReqProto GetProto(byte[] buffer) { Account_EnterGameReqProto proto = new Account_EnterGameReqProto(); using (MemoryStreamUtil ms = new MemoryStreamUtil(buffer)) { proto.RoleId = ms.ReadInt(); proto.ChannelId = ms.ReadInt(); } return(proto); }
public int GameServerId; //角色所在区服ID public byte[] ToArray() { using (MemoryStreamUtil ms = new MemoryStreamUtil()) { ms.WriteUShort(ProtoCode); ms.WriteByte(ClassId); ms.WriteUTF8String(RoleNickName); ms.WriteInt(GameServerId); return(ms.ToArray()); } }
public static Account_AddRoleReqProto GetProto(byte[] buffer) { Account_AddRoleReqProto proto = new Account_AddRoleReqProto(); using (MemoryStreamUtil ms = new MemoryStreamUtil(buffer)) { proto.ClassId = (byte)ms.ReadByte(); proto.RoleNickName = ms.ReadUTF8String(); proto.GameServerId = ms.ReadInt(); } return(proto); }
public int MsgCode; //消息码 public byte[] ToArray() { using (MemoryStreamUtil ms = new MemoryStreamUtil()) { ms.WriteUShort(ProtoCode); ms.WriteBool(IsSuccess); if (!IsSuccess) { ms.WriteInt(MsgCode); } return(ms.ToArray()); } }
public static Account_DeleteRoleRespProto GetProto(byte[] buffer) { Account_DeleteRoleRespProto proto = new Account_DeleteRoleRespProto(); using (MemoryStreamUtil ms = new MemoryStreamUtil(buffer)) { proto.IsSuccess = ms.ReadBool(); if (!proto.IsSuccess) { proto.MsgCode = ms.ReadInt(); } } return(proto); }
public byte[] ToArray() { using (MemoryStreamUtil ms = new MemoryStreamUtil()) { ms.WriteUShort(ProtoCode); ms.WriteInt(RoleCount); for (int i = 0; i < RoleCount; i++) { ms.WriteInt(RoleList[i].RoleId); ms.WriteUTF8String(RoleList[i].RoleNickName); ms.WriteByte(RoleList[i].RoleClass); ms.WriteInt(RoleList[i].RoleLevel); } return(ms.ToArray()); } }
public static Account_LoginGameServerRespProto GetProto(byte[] buffer) { Account_LoginGameServerRespProto proto = new Account_LoginGameServerRespProto(); using (MemoryStreamUtil ms = new MemoryStreamUtil(buffer)) { proto.RoleCount = ms.ReadInt(); proto.RoleList = new List <RoleItem>(); for (int i = 0; i < proto.RoleCount; i++) { RoleItem _Role = new RoleItem(); _Role.RoleId = ms.ReadInt(); _Role.RoleNickName = ms.ReadUTF8String(); _Role.RoleClass = (byte)ms.ReadByte(); _Role.RoleLevel = ms.ReadInt(); proto.RoleList.Add(_Role); } } return(proto); }
/// <summary> /// 制作一个数据包,该数据包是符合传给服务器的格式的(包头+包体) /// 当前工程的格式是包头:包体长度,包体:压缩标志+CRC校验码+加密的真正数据(异或算法)(协议编码+协议内容) /// 把private改为public,配合本机模式本地测试用 /// </summary> /// <param name="data">真实数据</param> /// <returns></returns> public byte[] MakeDataPkg(byte[] data) { byte[] returnBuffer = null; data = SecurityUtil.XorAlgorithm(data); //1、加密 bool isCompress = data.Length > mCompressMinSize; //2、压缩 if (isCompress) { //开始压缩 data = ZlibHelper.CompressBytes(data); } ushort crc16 = Crc16.CalculateCrc16(data); //3、CRC校验 using (MemoryStreamUtil stream = new MemoryStreamUtil()) { stream.WriteUShort((ushort)(data.Length + 3)); //写包头,+3是因为多了一个bool,一个ushort,一共3字节 stream.WriteBool(isCompress); //写压缩标志 stream.WriteUShort(crc16); //写CRC stream.Write(data, 0, data.Length); //写加密后的真实数据 returnBuffer = stream.ToArray(); } Debug.Log("数据包构建完毕!"); return(returnBuffer); }
/// <summary> /// 模拟要点:解客户端数据包,同时向正式代码模拟发送服务端数据包 /// 41课以后包体结构更复杂,包体=协议编号+协议内容 /// 43课以后数据包完全体为:包体=压缩标志+CRC校验码+异或算法后的真实数据(协议编号+协议内容) /// </summary> /// <param name="dataPkg">本地向服务器传什么数据</param> /// <param name="isDIYReturnMsg">是否由客户端决定服务器返回什么数据,默认为false,就是由服务端通过逻辑处理后返回一个伪真实的数据,如果为true,就是一个由客户端决定的纯伪造的数据</param> /// <param name="returnPkg">希望服务器向本地传什么数据</param> public void ServerOperator(byte[] dataPkg, bool isDIYReturnPkg = false) { if (isDIYReturnPkg == true) //向客户端返回的是客户端指定的数据包,不必再做下列处理 { return; } mReceiveStream.Position = mReceiveStream.Length; mReceiveStream.Write(dataPkg, 0, dataPkg.Length); //数据写进内存,等待操作 mReceiveStream.Position = 0; int currentMsgLen = mReceiveStream.ReadUShort(); //包体长度 int currentFullLen = 2 + currentMsgLen; //包头+包体长度 if (mReceiveStream.Length >= currentFullLen) //接收的数据包大于一个完整包的长度,表示至少有一个完整包传过来了 { byte[] buffer = new byte[currentMsgLen]; //此buffer为数据包,包体内容 mReceiveStream.Position = 2; //把包头去掉,剩下包体 mReceiveStream.Read(buffer, 0, currentMsgLen); //把数据读到buffer中 #region 43课以后完整版数据包增加以下内容 ushort CRC = 0; //CRC校验码 bool isCompress = false; //压缩标志 byte[] realDataBuffer = new byte[buffer.Length - 3]; //刨除CRC和压缩标志,真正数据部分 using (MemoryStreamUtil stream = new MemoryStreamUtil(buffer)) { isCompress = stream.ReadBool(); //获取压缩标志 CRC = stream.ReadUShort(); //获取CRC校验码 stream.Read(realDataBuffer, 0, realDataBuffer.Length); } ushort newCRC = Crc16.CalculateCrc16(realDataBuffer); //开始校验CRC if (CRC == newCRC) //校验通过 { if (isCompress) { realDataBuffer = ZlibHelper.DeCompressBytes(realDataBuffer); //解压 } realDataBuffer = SecurityUtil.XorAlgorithm(realDataBuffer); //解密,此时realDataBuffer是可以操作的数据 } else { Debug.Log("server:CRC verify failed!"); return; } #endregion #region 41课以后服务器增加以下内容 ushort protoCode = 0; byte[] protoContent = new byte[realDataBuffer.Length - 2]; //可操作数据buffer减去协议编号部分 #endregion using (MemoryStreamUtil stream = new MemoryStreamUtil(realDataBuffer)) { protoCode = stream.ReadUShort(); stream.Read(protoContent, 0, protoContent.Length); SocketDispatcher.Instance.Dispatch(protoCode, protoContent); //EventDispatcherS.Instance.Dispatch(protoCode, null, protoContent); } //41课以后使用网络协议,增加此部分判断逻辑 //43课以后使用观察者模式 //此处作为模拟器不使用观察者模式,采用模拟数据的方式简易处理 /* * if (protoCode == Leo_ProtoCodeDefine.RoleOperation_Login) * { * Leo_ProtoTest test = Leo_ProtoTest.ToObject(protoContent); * Debug.Log("服务器解析协议成功,协议编号:" + protoCode); * Debug.Log("ID:" + test.ID); * Debug.Log("name:" + test.name); * Leo_ProtoTest testReturn = new Leo_ProtoTest(); * testReturn.protoCode = Leo_ProtoCodeDefine.RoleOperation_Login; * testReturn.ID = 2002; * testReturn.name = "return"; * testReturn.price = 2.22f; * byte[] returnBuffer = Leo_SocketManager.Instance.MakeDataPkg(testReturn.ToArray()); //模拟服务器向客户端返回一条协议数据 * } * */ //Leo_SocketDispatcher.Instance.Dispatch(protoCode, protoContent); } else { Debug.Log("服务器解析数据包错误!"); } //2020-06-25新增,一次接收结束后把stream里的内容清空,保证下次接收的内容是新的 mReceiveStream.Position = 0; mReceiveStream.SetLength(0); }
private void ReceiveCallback(IAsyncResult result) { try { int len = client.EndReceive(result); if (len > 0) //接收到数据了 { mReceiveStream.Position = mReceiveStream.Length; mReceiveStream.Write(mReceiveBuffer, 0, mReceiveBuffer.Length); //数据写进内存,等待操作 //根据我们自定义数据包的格式,大于2字节代表有一个包传过来了 if (mReceiveStream.Length > 2) { while (true) { mReceiveStream.Position = 0; int currentMsgLen = mReceiveStream.ReadUShort(); //包体长度 int currentFullLen = 2 + currentMsgLen; //包头+包体长度 if (mReceiveStream.Length >= currentFullLen) //接收的数据包大于一个完整包的长度,表示至少有一个完整包传过来了 { byte[] buffer = new byte[currentMsgLen]; //此buffer为真实数据 mReceiveStream.Position = 2; //根据我们自定义的数据包格式,刨除前2位,后面的是真实数据 mReceiveStream.Read(buffer, 0, currentMsgLen); lock (mReceiveQueue) { mReceiveQueue.Enqueue(buffer); //加入接收队列中 } using (MemoryStreamUtil stream = new MemoryStreamUtil()) { string data = stream.ReadUTF8String(); // Debug.Log("data:" + data); } //上面是一个完整数据包处理过程,下面是本次接收多余的数据进行处理 int remainLen = (int)mReceiveStream.Length - currentFullLen; if (remainLen > 0) //本次接收的数据大于一个完整包时 { mReceiveStream.Position = currentFullLen; byte[] remainBuffer = new byte[remainLen]; mReceiveStream.Read(remainBuffer, 0, remainLen); //把剩余所有数据读进内存 //把流中数据清空 mReceiveStream.Position = 0; mReceiveStream.SetLength(0); mReceiveStream.Write(remainBuffer, 0, remainBuffer.Length); remainBuffer = null; } else { //把流中数据清空 mReceiveStream.Position = 0; mReceiveStream.SetLength(0); break; } } else { //还没收到完整包 break; } } } ReceiveMessage(); } else { Debug.Log("断开连接else"); } } catch (Exception e) { Debug.Log(e.Message); Debug.Log("断开连接catch"); } }