472 lines
17 KiB
C#
472 lines
17 KiB
C#
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>
|
||
/// 如果上一次是在Connecting,VerifyConnecting,Connected任何一种状态,当断开时,都应该调用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;
|
||
}
|
||
}
|
||
}
|