Socket通信

 

 

 

 

 

 

 

 

 

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);
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值