2023-04-03 11:04:31 +08:00

472 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
namespace BF
{
public class NetManager : ManagerBase
{
private class ClientInfo
{
public string Name;
public NetConnectStatus LastConnectStatus;
}
public const string MAIN_SOCKET_NAME = "0";
public const string CHAT_SOCKET_NAME = "1";
static NetManager instance;
private NetClient netClient;
private List<ClientInfo> clients = new List<ClientInfo>();
private event Action<int, uint, uint, byte[]> OnReceiveMsgLuaCallback;
private event Action<int> OnConnectedLuaCallback;
private event Action<int> OnDisconnectedLuaCallback;
private event Action<int> OnReconnectSuccessLuaCallback;
private event Action<int> OnReconnectLuaCallback;
private event Action<int, int, string> OnErrorLuaCallback;
public event Action<bool> luaAuthCallback;
private event Action<int, uint, uint, byte[]> OnDecodePbCallback;
public byte [] loginReqData = null;
public byte [] authReqData = null;
public byte [] ChatAuthReqData = null;
public string decodePbStr = null;
public uint rspGroup = 0;
public bool decodeFinish = false;
public static NetManager Create()
{
BFLog.LogAssert(instance == null, "This method only allows BFMain to call once");
instance = new NetManager();
instance.Init();
return instance;
}
public override void Init()
{
netClient = NetClient.Instance;
netClient.Init();
NetConfiguration configuration = new NetConfiguration
{
ServiceType = NetServiceType.TCPService,
ThreadName = "NetTCP"
};
netClient.SetupService(configuration);
netClient.Start();
}
public override void Update()
{
var count = clients.Count;
for (int i = 0; i < count; ++i)
{
var clientInfo = clients[i];
if(!ReferenceEquals(clientInfo, null))
{
INetIncomingMessage incomingMessage = null;
while ((incomingMessage = netClient.ReadMessage(clientInfo.Name)) != null)
{
HandleIncomingMessage(i, incomingMessage);
netClient.RecycleMessage(clientInfo.Name, incomingMessage);
}
}
}
}
public void InitNetClientCount(int count)
{
if (clients.Count < count)
{
for (int i = clients.Count; i < count; i++)
{
clients.Add(null);
}
}
}
/// <summary>
/// 根据消息类型,处理消息;
/// DebugMessage 内部调试信息release版本不会有任何此类消息
/// WarningMessage 警告信息release版本会包含有警告需要注意但不会影响正常运行
/// ErrorMessage 用于所有错误异常信息包含socket异常特别注意消息内的 ErrorCode在 HandleIncomingMessageError 中,有详细说明;
/// Data 数据消息代表从服务器接收到的所有PB消息密钥交换、心跳重连三种除外可以添加消息处理回调
/// StatusChange 当GetConnectStatus(string) 获取到的状态改变时,就收到这个消息,可以用来监听连接成功断开事件
/// </summary>
/// <param name="message"></param>
/// <exception cref="NotImplementedException"></exception>
private void HandleIncomingMessage(int clientId, INetIncomingMessage message)
{
// BFLog.Log("HandleIncomingMessage message.MessageType = " + message.MessageType.ToString());
switch (message.MessageType)
{
case NetIncomingMessageType.DebugMessage:
case NetIncomingMessageType.WarningMessage:
BFLog.Log("Debug Info {0} : {1} : {2}", clientId, message.ErrorCode, message.ErrorMsg);
break;
case NetIncomingMessageType.ErrorMessage:
HandleIncomingMessageError(clientId, message);
break;
case NetIncomingMessageType.Data:
HandleIncomingMessageData(clientId, message.Group, message.Seq, message.Data);
break;
case NetIncomingMessageType.StatusChange:
HandleConnectStatusChange(clientId, message);
break;
case NetIncomingMessageType.HeartBeatMessage:
break;
default:
BFLog.Log("Not Implemented Message");
break;
}
}
/// <summary>
/// 根据ErrorCode进行对应处理SocketError 为 -1 ~ 11004自定义错误码开始于20000
/// !!!特别注意
/// 如果 ErrorCode 是 NetErrorCode.PeerDisconnect代表当前连接已经被彻底断掉重连也失败了游戏应该关闭当前连接重新创建新的连接
/// </summary>
/// <param name="message"></param>
private void HandleIncomingMessageError(int clientId, INetIncomingMessage message)
{
OnErrorLuaCallback?.Invoke(clientId, message.ErrorCode, message.ErrorMsg);
}
/// <summary>
/// 处理接收到的服务器消息
/// </summary>
/// <param name="group"></param>
/// <param name="seq"></param>
/// <param name="data">PB 消息</param>
private void HandleIncomingMessageData(int clientId, uint group, uint seq, byte[] data)
{
OnReceiveMsgLuaCallback?.Invoke(clientId, group, seq, data);
}
private void HandleConnectStatusChange(int clientId, INetIncomingMessage message)
{
var clientInfo = clients[clientId];
// BFLog.Log("===== HandleConnectStatusChange lastConnectStatus = " + clientInfo.LastConnectStatus.ToString());
if(ReferenceEquals(clientInfo, null))
{
return;
}
NetConnectStatus status = message.ConnectStatus;
NetConnectStatus lastConnectStatus = clientInfo.LastConnectStatus;
// BFLog.Log("===== HandleConnectStatusChange status = " + status.ToString());
if (status == lastConnectStatus)
{
return;
}
clientInfo.LastConnectStatus = status;
if (lastConnectStatus == NetConnectStatus.Authing && status == NetConnectStatus.Decoding)
{
HandleDecodePbChange(clientId, message.Group, message.Seq, message.Data);
}
else if (lastConnectStatus == NetConnectStatus.Reconnecting && status == NetConnectStatus.Decoding)
{
HandleDecodePbChange(clientId, message.Group, message.Seq, message.Data);
}
else if (lastConnectStatus == NetConnectStatus.Reconnecting && status == NetConnectStatus.Decoding2)
{
HandleDecodePbChange(clientId, message.Group, message.Seq, message.Data);
}
else if (lastConnectStatus == NetConnectStatus.Authing && status == NetConnectStatus.Unauthorized)
{
luaAuthCallback?.Invoke(false);
}
else if (lastConnectStatus == NetConnectStatus.Reconnecting && status == NetConnectStatus.Unauthorized)
{
luaAuthCallback?.Invoke(false);
}
else if (lastConnectStatus == NetConnectStatus.Decoding2 && status == NetConnectStatus.Connected)
{
OnReconnectSuccessLuaCallback?.Invoke(clientId);
}
else if (lastConnectStatus != NetConnectStatus.Connected && status == NetConnectStatus.Connected)
{
OnConnectedLuaCallback?.Invoke(clientId);
}
else if (LastConnectStatusIsTryOrConnect(lastConnectStatus) && status == NetConnectStatus.Disconnected)
{
OnDisconnectedLuaCallback?.Invoke(clientId);
}
else if (lastConnectStatus != NetConnectStatus.Reconnecting && status == NetConnectStatus.Reconnecting)
{
OnReconnectLuaCallback?.Invoke(clientId);
}
}
public void HandleDecodePbChange(int clientId, uint group, uint seq, byte[] data)
{
decodeFinish = false;
OnDecodePbCallback?.Invoke(clientId, group, seq, data);
}
/// <summary>
/// 如果上一次是在ConnectingVerifyConnectingConnected任何一种状态当断开时都应该调用DisconnectEvent事件
/// </summary>
/// <returns></returns>
private bool LastConnectStatusIsTryOrConnect(NetConnectStatus lastConnectStatus)
{
return lastConnectStatus == NetConnectStatus.Connected ||
lastConnectStatus == NetConnectStatus.Connecting ||
lastConnectStatus == NetConnectStatus.VerifyConnecting ||
lastConnectStatus == NetConnectStatus.Reconnecting;
}
public string GetConnectIP(int clientId)
{
var clientInfo = clients[clientId];
if (ReferenceEquals(clientInfo, null))
{
return "";
}
return netClient.GetConnectIP(clientInfo.Name);
}
public bool IsConnected(int clientId)
{
var clientInfo = clients[clientId];
if (ReferenceEquals(clientInfo, null))
{
return false;
}
return netClient.GetConnectStatus(clientInfo.Name) == NetConnectStatus.Connected;
}
public bool IsDisconnected(int clientId)
{
var clientInfo = clients[clientId];
if (ReferenceEquals(clientInfo, null))
{
return true;
}
var currStatus = netClient.GetConnectStatus(clientInfo.Name);
return currStatus == NetConnectStatus.Disconnecting ||
currStatus == NetConnectStatus.Disconnected;
}
public bool IsAvailable(int clientId)
{
var clientInfo = clients[clientId];
if (ReferenceEquals(clientInfo, null))
{
return false;
}
var currStatus = netClient.GetConnectStatus(clientInfo.Name);
return currStatus == NetConnectStatus.Connected ||
currStatus == NetConnectStatus.Connecting ||
currStatus == NetConnectStatus.Reconnecting ||
currStatus == NetConnectStatus.VerifyConnecting;
}
public bool IsClosed(int clientId)
{
var clientInfo = clients[clientId];
if (ReferenceEquals(clientInfo, null))
{
return true;
}
var currStatus = netClient.GetConnectStatus(clientInfo.Name);
return currStatus == NetConnectStatus.Disconnected;
}
public void Reconnect(int clientId)
{
var clientInfo = clients[clientId];
if (ReferenceEquals(clientInfo, null))
{
return;
}
netClient.Reconnect(clientInfo.Name);
}
public long GetServerTimestamp(int clientId)
{
var clientInfo = clients[clientId];
if (ReferenceEquals(clientInfo, null))
{
return 0;
}
return netClient.GetServerTimestamp(clientInfo.Name);
}
/// <summary>
/// 使用configuration创建连接
/// </summary>
public void ConnectWithDomainName(int clientId, string clientName, string domainName, int port)
{
NetConnectConfiguration configuration = new NetConnectConfiguration(NetServiceType.TCPService, clientName);
/**
* 启用的消息类型
* DebugMessage release版本中不会收到此类消息
* WarningMessage :不需要处理,但要注意;
* ErrorMessage :必须启用,用以接受异常消息;
* Data 应用消息,默认启用;
*
* 其他消息暂未使用
*/
configuration.EnableMessageType(NetIncomingMessageType.DebugMessage);
configuration.EnableMessageType(NetIncomingMessageType.WarningMessage);
configuration.EnableMessageType(NetIncomingMessageType.ErrorMessage);
ConnectWithConfiguration(clientId, configuration, domainName, port);
}
public void ConnectWithConfiguration(int clientId, NetConnectConfiguration configuration, string domainName, int port)
{
ClientInfo clientInfo = new ClientInfo();
clientInfo.Name = configuration.UniqueIdentifier;
clientInfo.LastConnectStatus = NetConnectStatus.InvalidConnect;
clients[clientId] = clientInfo;
netClient.Connect(configuration, domainName, port);
}
public void Send(int clientId, uint group, byte cmd, byte[] data)
{
/**
* 直接发送数据
*/
var clientInfo = clients[clientId];
if(ReferenceEquals(clientInfo, null))
{
return;
}
netClient.Send(clientInfo.Name, group, cmd, data);
}
/// <summary>
/// 关闭目标连接
/// </summary>
public void Close(int clientId)
{
var clientInfo = clients[clientId];
if(ReferenceEquals(clientInfo, null))
{
return;
}
clients[clientId] = null;
netClient.Close(clientInfo.Name);
}
public byte[] GetAuthReqData()
{
return authReqData;
}
public byte[] GetChatAuthReqData()
{
return ChatAuthReqData;
}
public byte[] GetLoginReqData()
{
return loginReqData;
}
public bool GetDecodeStataus()
{
return decodeFinish;
}
public string GetDecodePbStr()
{
return decodePbStr;
}
public uint GetDecodeGroup()
{
return rspGroup;
}
public void AddLuaOnReceiveMessage(Action<int, uint, uint, byte[]> luaFunc)
{
OnReceiveMsgLuaCallback = luaFunc;
}
public void RemoveLuaOnReceiveMessage()
{
OnReceiveMsgLuaCallback = null;
}
public void AddLuaOnConnected(Action<int> luaFunc)
{
OnConnectedLuaCallback = luaFunc;
}
public void RemoveLuaOnConnected()
{
OnConnectedLuaCallback = null;
}
public void AddLuaOnDisconnected(Action<int> luaFunc)
{
OnDisconnectedLuaCallback = luaFunc;
}
public void RemoveLuaOnDisconnected()
{
OnDisconnectedLuaCallback = null;
}
public void AddLuaOnReconnectSuccess(Action<int> luaFunc)
{
OnReconnectSuccessLuaCallback = luaFunc;
}
public void RemoveLuaOnReconnectSuccess()
{
OnReconnectSuccessLuaCallback = null;
}
public void AddLuaOnReconnect(Action<int> luaFunc)
{
OnReconnectLuaCallback = luaFunc;
}
public void RemoveLuaOnReconnect()
{
OnReconnectLuaCallback = null;
}
public void SetLuaAuthCallback(Action<bool> callback)
{
luaAuthCallback = callback;
}
public void SetLuaOnDecodePbCallback(Action<int, uint, uint, byte[]> luaFunc)
{
OnDecodePbCallback = luaFunc;
}
public void RemoveLuaOnDecodePbCallback()
{
OnDecodePbCallback = null;
}
public void AddLuaOnError(Action<int, int, string> luaFunc)
{
OnErrorLuaCallback = luaFunc;
}
public void RemoveLuaOnError()
{
OnErrorLuaCallback = null;
}
public void RemoveAllLuaCallback()
{
OnReceiveMsgLuaCallback = null;
OnConnectedLuaCallback = null;
OnDisconnectedLuaCallback = null;
OnReconnectSuccessLuaCallback = null;
OnReconnectLuaCallback = null;
OnErrorLuaCallback = null;
OnDecodePbCallback = null;
}
public override void Destroy()
{
RemoveAllLuaCallback();
netClient.Shutdown();
netClient = null;
}
}
}