TestSocket 测试脚本
using UnityEngine;
using YouYou;
public class TestSocket : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
GameEntry.Socket.ConnectToMainSocket("192.168.1.9", 1038);
}
else if (Input.GetKeyDown(KeyCode.B))
{
System_SendLocalTimeProto proto = new System_SendLocalTimeProto();
GameEntry.Socket.SendMessage(proto.ToArray().ToString());
}
}
}
连接成功后的回调
把当前的访问器进链表
接受数据
接受数据的回调
#region ReceiveCallBack 接收数据回调
/// <summary>
/// 接收数据回调
/// </summary>
/// <param name="ar"></param>
private void ReceiveCallBack(IAsyncResult ar)
{
try
{
int len = m_Client.EndReceive(ar);
if (len > 0)
{
//已经接收到数据
//把接收到数据 写入缓冲数据流的尾部
m_ReceiveMS.Position = m_ReceiveMS.Length;
//把指定长度的字节 写入数据流
m_ReceiveMS.Write(m_ReceiveBuffer, 0, len);
//如果缓存数据流的长度>2 说明至少有个不完整的包过来了
//为什么这里是2 因为我们客户端封装数据包 用的ushort 长度就是2
if (m_ReceiveMS.Length > 2)
{
//进行循环 拆分数据包
while (true)
{
//把数据流指针位置放在0处
m_ReceiveMS.Position = 0;
//currMsgLen = 包体的长度
int currMsgLen = m_ReceiveMS.ReadUShort();
//currFullMsgLen 总包的长度=包头长度+包体长度
int currFullMsgLen = 2 + currMsgLen;
//如果数据流的长度>=整包的长度 说明至少收到了一个完整包
if (m_ReceiveMS.Length >= currFullMsgLen)
{
//至少收到一个完整包
//定义包体的byte[]数组
byte[] buffer = new byte[currMsgLen];
//把数据流指针放到2的位置 也就是包体的位置
m_ReceiveMS.Position = 2;
//把包体读到byte[]数组
m_ReceiveMS.Read(buffer, 0, currMsgLen);
lock (m_ReceiveQueue)
{
m_ReceiveQueue.Enqueue(buffer);
}
//==============处理剩余字节数组===================
//剩余字节长度
int remainLen = (int)m_ReceiveMS.Length - currFullMsgLen;
if (remainLen > 0)
{
//把指针放在第一个包的尾部
m_ReceiveMS.Position = currFullMsgLen;
//定义剩余字节数组
byte[] remainBuffer = new byte[remainLen];
//把数据流读到剩余字节数组
m_ReceiveMS.Read(remainBuffer, 0, remainLen);
//清空数据流
m_ReceiveMS.Position = 0;
m_ReceiveMS.SetLength(0);
//把剩余字节数组重新写入数据流
m_ReceiveMS.Write(remainBuffer, 0, remainBuffer.Length);
remainBuffer = null;
}
else
{
//没有剩余字节
//清空数据流
m_ReceiveMS.Position = 0;
m_ReceiveMS.SetLength(0);
break;
}
}
else
{
//还没有收到完整包
break;
}
}
}
//进行下一次接收数据包
ReceiveMsg();
}
else
{
//服务器断开连接
Debug.Log(string.Format("服务器{0}断开连接", m_Client.RemoteEndPoint.ToString()));
}
}
catch
{
//服务器断开连接
Debug.Log(string.Format("服务器{0}断开连接", m_Client.RemoteEndPoint.ToString()));
}
}
#endregion
工具生成的下面脚本
using YouYou;
/// <summary>
/// 客户端发送本地时间
/// </summary>
public struct System_SendLocalTimeProto : IProto
{
public ushort ProtoCode { get { return 14001; } }
public string ProtoEnName { get { return "System_SendLocalTime"; } }
public float LocalTime; //本地时间(毫秒)
public byte[] ToArray()
{
MMO_MemoryStream ms = GameEntry.Socket.SocketSendMS;
ms.SetLength(0);
ms.WriteUShort(ProtoCode);
ms.WriteFloat(LocalTime);
return ms.ToArray();
}
public static System_SendLocalTimeProto GetProto(byte[] buffer)
{
System_SendLocalTimeProto proto = new System_SendLocalTimeProto();
MMO_MemoryStream ms = GameEntry.Socket.SocketReceiveMS;
ms.SetLength(0);
ms.Write(buffer, 0, buffer.Length);
ms.Position = 0;
proto.LocalTime = ms.ReadFloat();
return proto;
}
}
组件中监听返回消息
发送心跳
#region CheckSendQueue 检查发送队列
/// <summary>
/// 检查发送队列
/// </summary>
private void CheckSendQueue()
{
if (m_SendCount >= GameEntry.Socket.MaxSendCount)
{
//等待下一帧发送
m_SendCount = 0;
return;
}
lock (m_SendQueue)
{
if (m_SendQueue.Count > 0 || m_IsHasUnDealBytes)
{
MMO_MemoryStream ms = m_SocketSendMS;
ms.SetLength(0);
if (m_IsHasUnDealBytes)
{
m_IsHasUnDealBytes = false;
ms.Write(m_UnDealBytes, 0, m_UnDealBytes.Length);
}
while (true)
{
if (m_SendQueue.Count == 0) break;
//取出一个字节数组
byte[] buffer = m_SendQueue.Dequeue();
if (buffer.Length + ms.Length <= GameEntry.Socket.MaxSendByteCount)
{
ms.Write(buffer, 0, buffer.Length);
}
else
{
//已经取出来一个要发送的字节数组
m_UnDealBytes = buffer;
m_IsHasUnDealBytes = true;
break;
}
}
m_SendCount++;
Send(ms.ToArray());
}
}
}
#endregion
监听的协议
using YouYou;
/// <summary>
/// Socket协议监听(工具生成)
/// </summary>
public sealed class SocketProtoListener
{
/// <summary>
/// 添加协议监听
/// </summary>
public static void AddProtoListener()
{
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.System_HeartbeatReturn, System_HeartbeatReturnHandler.OnSystem_HeartbeatReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.System_GameServerConfigReturn, System_GameServerConfigReturnHandler.OnSystem_GameServerConfigReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.RoleOperation_LogOnGameServerReturn, RoleOperation_LogOnGameServerReturnHandler.OnRoleOperation_LogOnGameServerReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.RoleOperation_CreateRoleReturn, RoleOperation_CreateRoleReturnHandler.OnRoleOperation_CreateRoleReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.RoleOperation_DeleteRoleReturn, RoleOperation_DeleteRoleReturnHandler.OnRoleOperation_DeleteRoleReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.RoleOperation_EnterGameReturn, RoleOperation_EnterGameReturnHandler.OnRoleOperation_EnterGameReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.RoleOperation_SelectRoleInfoReturn, RoleOperation_SelectRoleInfoReturnHandler.OnRoleOperation_SelectRoleInfoReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.Task_SearchTaskReturn, Task_SearchTaskReturnHandler.OnTask_SearchTaskReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.Shop_BuyProductReturn, Shop_BuyProductReturnHandler.OnShop_BuyProductReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.Backpack_GoodsChangeReturn, Backpack_GoodsChangeReturnHandler.OnBackpack_GoodsChangeReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.Backpack_SearchReturn, Backpack_SearchReturnHandler.OnBackpack_SearchReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.Goods_SearchEquipDetailReturn, Goods_SearchEquipDetailReturnHandler.OnGoods_SearchEquipDetailReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.Goods_SellToSysReturn, Goods_SellToSysReturnHandler.OnGoods_SellToSysReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.Goods_UseItemReturn, Goods_UseItemReturnHandler.OnGoods_UseItemReturn);
GameEntry.Event.SocketEvent.AddEventListener(ProtoCodeDef.Goods_EquipPutReturn, Goods_EquipPutReturnHandler.OnGoods_EquipPutReturn);
}
/// <summary>
/// 移除协议监听
/// </summary>
public static void RemoveProtoListener()
{
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.System_HeartbeatReturn, System_HeartbeatReturnHandler.OnSystem_HeartbeatReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.System_GameServerConfigReturn, System_GameServerConfigReturnHandler.OnSystem_GameServerConfigReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.RoleOperation_LogOnGameServerReturn, RoleOperation_LogOnGameServerReturnHandler.OnRoleOperation_LogOnGameServerReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.RoleOperation_CreateRoleReturn, RoleOperation_CreateRoleReturnHandler.OnRoleOperation_CreateRoleReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.RoleOperation_DeleteRoleReturn, RoleOperation_DeleteRoleReturnHandler.OnRoleOperation_DeleteRoleReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.RoleOperation_EnterGameReturn, RoleOperation_EnterGameReturnHandler.OnRoleOperation_EnterGameReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.RoleOperation_SelectRoleInfoReturn, RoleOperation_SelectRoleInfoReturnHandler.OnRoleOperation_SelectRoleInfoReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.Task_SearchTaskReturn, Task_SearchTaskReturnHandler.OnTask_SearchTaskReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.Shop_BuyProductReturn, Shop_BuyProductReturnHandler.OnShop_BuyProductReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.Backpack_GoodsChangeReturn, Backpack_GoodsChangeReturnHandler.OnBackpack_GoodsChangeReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.Backpack_SearchReturn, Backpack_SearchReturnHandler.OnBackpack_SearchReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.Goods_SearchEquipDetailReturn, Goods_SearchEquipDetailReturnHandler.OnGoods_SearchEquipDetailReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.Goods_SellToSysReturn, Goods_SellToSysReturnHandler.OnGoods_SellToSysReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.Goods_UseItemReturn, Goods_UseItemReturnHandler.OnGoods_UseItemReturn);
GameEntry.Event.SocketEvent.RemoveEventListener(ProtoCodeDef.Goods_EquipPutReturn, Goods_EquipPutReturnHandler.OnGoods_EquipPutReturn);
}
}
监听到消息执行,打印出时间
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YouYou;
/// <summary>
/// 服务器返回心跳(工具只生成一次)
/// </summary>
public sealed class System_HeartbeatReturnHandler
{
public static void OnSystem_HeartbeatReturn(byte[] buffer)
{
System_HeartbeatReturnProto proto = System_HeartbeatReturnProto.GetProto(buffer);
#if DEBUG_LOG_PROTO
Debug.Log("<color=#00eaff>接收消息:</color><color=#00ff9c>" + proto.ProtoEnName + " " + proto.ProtoCode + "</color>");
Debug.Log("<color=#c5e1dc>==>>" + JsonUtility.ToJson(proto) + "</color>");
#endif
float localTime = proto.LocalTime;
long serverTime = proto.ServerTime;
//得到ping值
GameEntry.Socket.PingValue = (int)((Time.realtimeSinceStartup * 1000 - localTime) * 0.5f);
//得到本地计算的服务器时间
GameEntry.Socket.GameServerTime = serverTime - GameEntry.Socket.PingValue;
Debug.Log("服务器时间==" + GameEntry.Socket.GameServerTime);
Debug.Log("得到ping值==" + GameEntry.Socket.PingValue);
}
}