////////////////////////////////////////////////////////////////////////// // // 文件:Assets/Code/Scripts/Gameplay/Net/Client/NetClient.cs // 作者:Xoen Xie // 时间:2023/07/18 // 描述:网络客户端 // 说明: // ////////////////////////////////////////////////////////////////////////// using UnityEngine; using Framework; using System; namespace Gameplay.Net { public sealed class NetClient : INetHandler { private string m_sIP; private int m_nPort; private NetTcp m_Connection; private NetReader m_Reader; public bool m_bHandshake; private float m_fLastHeartbeatTime = 0; public uint mID; private DH64 m_dh64; private ulong m_nPrivateKey; private ulong m_nPublicKey; public NetClient() { m_Reader = new NetReader(); m_Connection = new NetTcp(); byte[] data = BitConverter.GetBytes((ulong)1234567890); m_Connection.Cipher = new RC4Cipher(data); m_dh64 = new DH64(); m_dh64.KeyPair(out m_nPrivateKey, out m_nPublicKey); } public bool Create(string sIP, int nPort) { m_sIP = sIP; m_nPort = nPort; m_Connection.Create(this); m_bHandshake = false; m_fLastHeartbeatTime = 0; return true; } public void Release() { m_Connection.Release(); m_bHandshake = false; } public void DisConnect() { m_Connection.DisConnect(); } public bool Connect() { if (!m_Connection.Connect(m_sIP, m_nPort)) { return false; } Framework.EventManager.Instance.Send(Framework.EventManager.EventName.NetConnecting, mID); return true; } public void SendMessage(IMessage message, uint nRawID = 0) { if (m_Connection == null || !m_Connection.mIsConnected) { DebugUtil.LogError("NetClient.SendMessage connection not connected, msg id={0}", message.ID); return; } m_Connection.Send((ushort)message.ID, message.Export(), nRawID); } public void Update() { m_Connection.Dispath(); if (!m_Connection.mIsConnected) return; if (m_bHandshake) { float fCurTime = Time.realtimeSinceStartup; if (fCurTime >= Constants.HEARTBEAT_INTERVAL + m_fLastHeartbeatTime) { m_fLastHeartbeatTime = fCurTime; SendHeartbeat(); } } } public void OnConnected() { Framework.EventManager.Instance.Send(Framework.EventManager.EventName.NetConnected, mID); DebugUtil.Log("NetClient::OnConnected ip={0}, port={1}", m_sIP, m_nPort); // 连接成功发送握手消息 SendHandshake(); m_fLastHeartbeatTime = 0; } public void OnRecv(byte[] data) { m_Reader.Init(data); ushort nMsgID = 0; m_Reader.ReadUShort(out nMsgID); //减少心跳包的Log if ((NLDMID.MSGID)nMsgID != NLDMID.MSGID.GtCltHeartbeat) { DebugUtil.Log("NetClient OnRecv, msg id={0}", (NLDMID.MSGID)nMsgID); } IMessage message = NetManager.Instance.GetMessage((NLDMID.MSGID)nMsgID); if (message != null) { message.Import(data, 2, data.Length - 2); message.Execute(this); } else { DebugUtil.LogError("NetClient OnRecv message not found, msg id={0}", (NLDMID.MSGID)nMsgID); } } public void OnError(NetError nErrorCode) { DebugUtil.LogError("NetClient::OnError, 网络出错,错误码={0}", nErrorCode); Framework.EventManager.Instance.Send(Framework.EventManager.EventName.NetError, mID); } private void SendHandshake() { var msg = NetManager.Instance.GetMessage(NLDMID.MSGID.CltGtHandshake) as MSG_Clt_Gt_Handshake; msg.mPB.ClientPublicKey = m_nPublicKey; SendMessage(NetManager.Instance.GetMessage(NLDMID.MSGID.CltGtHandshake)); } public void SendHeartbeat() { MSG_Clt_Gt_Heartbeat msg = NetManager.Instance.GetMessage(NLDMID.MSGID.CltGtHeartbeat) as MSG_Clt_Gt_Heartbeat; msg.mPB.Time = PhxhSDK.Utils.GetTimeStampMilliseconds(); SendMessage(msg); } public void OnHandshake(ulong nServerPublicKey) { var secret = m_dh64.Secret(m_nPrivateKey, nServerPublicKey); byte[] data = BitConverter.GetBytes(secret); m_Connection.Cipher = new RC4Cipher(data); DebugUtil.Log("NetClient.OnHandshake start ..."); Framework.EventManager.Instance.Send(Framework.EventManager.EventName.NetHandshakeDone, mID); m_bHandshake = true; } } }