协议和基本逻辑

This commit is contained in:
sin365 2024-01-16 18:04:15 +08:00
parent 4c3a242d8a
commit 2cd5aa4383
24 changed files with 5943 additions and 0 deletions

BIN
Lib/Google.Protobuf.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NoSugarNet.ServerCore.Common
{
/// <summary>
/// 压缩适配器
/// </summary>
public class CompressAdapter
{
IDataCompress mIDataCompress;
public CompressAdapter(ushort type)
{
switch (type)
{
//不压缩
case 0:
mIDataCompress = new NoCompress();
break;
//TODO 其他压缩对比
default:
mIDataCompress = new NoCompress();
break;
}
}
public byte[] Compress(byte[] data)
{
return mIDataCompress.Compress(data);
}
public byte[] Decompress(byte[] data)
{
return mIDataCompress.Decompress(data);
}
}
public interface IDataCompress
{
public byte[] Compress(byte[] data);
public byte[] Decompress(byte[] data);
}
public class NoCompress : IDataCompress
{
public byte[] Compress(byte[] data)
{
return data;
}
public byte[] Decompress(byte[] data)
{
return data;
}
}
}

View File

@ -0,0 +1,20 @@
namespace ServerCore.Common
{
public static class Helper
{
public static long GetNowTimeStamp()
{
return GetTimeStamp(DateTime.Now);
}
/// <summary>
/// 获取时间戳
/// </summary>
/// <returns></returns>
public static long GetTimeStamp(DateTime dt)
{
TimeSpan ts = dt - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalSeconds);
}
}
}

View File

@ -0,0 +1,22 @@
using Google.Protobuf;
namespace ServerCore.Common
{
public static class ProtoBufHelper
{
public static byte[] Serizlize(IMessage msg)
{
return msg.ToByteArray();
}
public static T DeSerizlize<T>(byte[] bytes)
{
var msgType = typeof(T);
object msg = Activator.CreateInstance(msgType);
((IMessage)msg).MergeFrom(bytes);
return (T)msg;
}
}
}

View File

@ -0,0 +1,9 @@
namespace ServerCore.Event
{
public enum EEvent
{
// 添加你自己需要的事件类型
OnUserJoin,
OnUserLeave
}
}

View File

@ -0,0 +1,216 @@
using ServerCore.Manager;
namespace ServerCore.Event
{
public class EventSystem
{
private static EventSystem instance = new EventSystem();
public static EventSystem Instance { get { return instance; } }
private Dictionary<EEvent, List<Delegate>> eventDic = new Dictionary<EEvent, List<Delegate>>(128);
private EventSystem() { }
#region RegisterEvent
public void RegisterEvent(EEvent evt, Action callback)
{
InterRegisterEvent(evt, callback);
}
public void RegisterEvent<T1>(EEvent evt, Action<T1> callback)
{
InterRegisterEvent(evt, callback);
}
public void RegisterEvent<T1, T2>(EEvent evt, Action<T1, T2> callback)
{
InterRegisterEvent(evt, callback);
}
public void RegisterEvent<T1, T2, T3>(EEvent evt, Action<T1, T2, T3> callback)
{
InterRegisterEvent(evt, callback);
}
public void RegisterEvent<T1, T2, T3, T4>(EEvent evt, Action<T1, T2, T3, T4> callback)
{
InterRegisterEvent(evt, callback);
}
private void InterRegisterEvent(EEvent evt, Delegate callback)
{
if (eventDic.ContainsKey(evt))
{
if (eventDic[evt].IndexOf(callback) < 0)
{
eventDic[evt].Add(callback);
}
}
else
{
eventDic.Add(evt, new List<Delegate>() { callback });
}
}
#endregion
#region UnregisterEvent
public void UnregisterEvent(EEvent evt, Action callback)
{
Delegate tempDelegate = callback;
InterUnregisterEvent(evt, tempDelegate);
}
public void UnregisterEvent<T1>(EEvent evt, Action<T1> callback)
{
Delegate tempDelegate = callback;
InterUnregisterEvent(evt, tempDelegate);
}
public void UnregisterEvent<T1, T2>(EEvent evt, Action<T1, T2> callback)
{
Delegate tempDelegate = callback;
InterUnregisterEvent(evt, tempDelegate);
}
public void UnregisterEvent<T1, T2, T3>(EEvent evt, Action<T1, T2, T3> callback)
{
Delegate tempDelegate = callback;
InterUnregisterEvent(evt, tempDelegate);
}
public void UnregisterEvent<T1, T2, T3, T4>(EEvent evt, Action<T1, T2, T3, T4> callback)
{
Delegate tempDelegate = callback;
InterUnregisterEvent(evt, tempDelegate);
}
private void InterUnregisterEvent(EEvent evt, Delegate callback)
{
if (eventDic.ContainsKey(evt))
{
eventDic[evt].Remove(callback);
if (eventDic[evt].Count == 0) eventDic.Remove(evt);
}
}
#endregion
#region PostEvent
public void PostEvent<T1, T2, T3, T4>(EEvent evt, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
List<Delegate> eventList = GetEventList(evt);
if (eventList != null)
{
foreach (Delegate callback in eventList)
{
try
{
((Action<T1, T2, T3, T4>)callback)(arg1, arg2, arg3, arg4);
}
catch (Exception e)
{
ServerManager.g_Log.Error(e.Message);
}
}
}
}
public void PostEvent<T1, T2, T3>(EEvent evt, T1 arg1, T2 arg2, T3 arg3)
{
List<Delegate> eventList = GetEventList(evt);
if (eventList != null)
{
foreach (Delegate callback in eventList)
{
try
{
((Action<T1, T2, T3>)callback)(arg1, arg2, arg3);
}
catch (Exception e)
{
ServerManager.g_Log.Error(e.Message);
}
}
}
}
public void PostEvent<T1, T2>(EEvent evt, T1 arg1, T2 arg2)
{
List<Delegate> eventList = GetEventList(evt);
if (eventList != null)
{
foreach (Delegate callback in eventList)
{
try
{
((Action<T1, T2>)callback)(arg1, arg2);
}
catch (Exception e)
{
ServerManager.g_Log.Error(e.Message);
}
}
}
}
public void PostEvent<T>(EEvent evt, T arg)
{
List<Delegate> eventList = GetEventList(evt);
if (eventList != null)
{
foreach (Delegate callback in eventList)
{
try
{
((Action<T>)callback)(arg);
}
catch (Exception e)
{
ServerManager.g_Log.Error(e.Message + ", method name : " + callback.Method);
}
}
}
}
public void PostEvent(EEvent evt)
{
List<Delegate> eventList = GetEventList(evt);
if (eventList != null)
{
foreach (Delegate callback in eventList)
{
try
{
((Action)callback)();
}
catch (Exception e)
{
ServerManager.g_Log.Error(e.Message);
}
}
}
}
#endregion
/// <summary>
/// 获取所有事件
/// </summary>
/// <param name="evt"></param>
/// <returns></returns>
private List<Delegate> GetEventList(EEvent evt)
{
if (eventDic.ContainsKey(evt))
{
List<Delegate> tempList = eventDic[evt];
if (null != tempList)
{
return tempList;
}
}
return null;
}
}
}

View File

@ -0,0 +1,29 @@
using AxibugProtobuf;
using ServerCore.Common;
using ServerCore.NetWork;
using System.Net.Sockets;
namespace ServerCore.Manager
{
public class ChatManager
{
public ChatManager()
{
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdChatmsg, RecvPlayerChatMsg);
}
public void RecvPlayerChatMsg(Socket sk, byte[] reqData)
{
ClientInfo _c = ServerManager.g_ClientMgr.GetClientForSocket(sk);
ServerManager.g_Log.Debug("收到聊天消息请求");
Protobuf_ChatMsg msg = ProtoBufHelper.DeSerizlize<Protobuf_ChatMsg>(reqData);
byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_ChatMsg_RESP()
{
ChatMsg = msg.ChatMsg,
NickName = _c.Account,
Date = Helper.GetNowTimeStamp()
});
ServerManager.g_ClientMgr.ClientSendALL((int)CommandID.CmdChatmsg, (int)ErrorCode.ErrorOk, respData);
}
}
}

View File

@ -0,0 +1,234 @@
using AxibugProtobuf;
using System.Net.Sockets;
using System.Timers;
namespace ServerCore.Manager
{
public class ClientInfo
{
public long UID { get; set; }
public string Account { get; set; }
public Socket _socket { get; set; }
public bool IsOffline { get; set; } = false;
public DateTime LogOutDT { get; set; }
}
public class ClientManager
{
private List<ClientInfo> ClientList = new List<ClientInfo>();
private Dictionary<Socket, ClientInfo> _DictSocketClient = new Dictionary<Socket, ClientInfo>();
private Dictionary<long?, ClientInfo> _DictUIDClient = new Dictionary<long?, ClientInfo>();
private long TestUIDSeed = 0;
private System.Timers.Timer _ClientCheckTimer;
private long _RemoveOfflineCacheMin;
/// <summary>
/// 初始化并指定检查时间
/// </summary>
/// <param name="ticktime">tick检查毫秒数</param>
/// <param name="RemoveOfflineCache">清理掉线分钟数</param>
public void Init(long ticktime, long RemoveOfflineCacheMin)
{
//换算成毫秒
_RemoveOfflineCacheMin = RemoveOfflineCacheMin;
_ClientCheckTimer = new System.Timers.Timer();
_ClientCheckTimer.Interval = ticktime;
_ClientCheckTimer.AutoReset = true;
_ClientCheckTimer.Elapsed += new ElapsedEventHandler(ClientCheckClearOffline_Elapsed);
_ClientCheckTimer.Enabled = true;
}
public long GetNextUID()
{
return ++TestUIDSeed;
}
private void ClientCheckClearOffline_Elapsed(object sender, ElapsedEventArgs e)
{
DateTime CheckDT = DateTime.Now.AddMinutes(-1 * _RemoveOfflineCacheMin);
ClientInfo[] OfflineClientlist = ClientList.Where(w => w.IsOffline == true && w.LogOutDT < CheckDT).ToArray();
Console.WriteLine("开始清理离线过久的玩家的缓存");
for (int i = 0; i < OfflineClientlist.Length; i++)
{
//to do 掉线处理
RemoveClient(OfflineClientlist[i]);
}
GC.Collect();
}
//通用处理
#region clientlist
public ClientInfo JoinNewClient(Protobuf_Login data, Socket _socket)
{
//也许这个函数需加lock
ClientInfo cinfo = GetClientForSocket(_socket);
//如果连接还在
if (cinfo != null)
{
cinfo.IsOffline = false;
}
else
{
cinfo = new ClientInfo()
{
UID = GetNextUID(),
_socket = _socket,
Account = data.Account,
IsOffline = false,
};
AddClient(cinfo);
}
return cinfo;
}
/// <summary>
/// 增加用户
/// </summary>
/// <param name="client"></param>
void AddClient(ClientInfo clientInfo)
{
try
{
Console.WriteLine("追加连接玩家 UID=>" + clientInfo.UID + " | " + clientInfo.Account);
lock (ClientList)
{
_DictUIDClient.Add(clientInfo.UID, clientInfo);
_DictSocketClient.Add(clientInfo._socket, clientInfo);
ClientList.Add(clientInfo);
}
}
catch (Exception ex)
{
ex.ToString();
}
}
/// <summary>
/// 清理连接
/// </summary>
/// <param name="client"></param>
public void RemoveClient(ClientInfo client)
{
lock (ClientList)
{
if (_DictUIDClient.ContainsKey(client.UID))
_DictUIDClient.Remove(client.UID);
if (_DictSocketClient.ContainsKey(client._socket))
_DictSocketClient.Remove(client._socket);
ClientList.Remove(client);
}
}
/// <summary>
/// 清理连接
/// </summary>
/// <param name="client"></param>
public bool GetClientByUID(long uid,out ClientInfo client)
{
lock (ClientList)
{
if (!_DictUIDClient.ContainsKey(uid))
{
client = null;
return false;
}
client = _DictUIDClient[uid];
return true;
}
}
public ClientInfo GetClientForSocket(Socket sk)
{
return _DictSocketClient.ContainsKey(sk) ? _DictSocketClient[sk] : null;
}
/// <summary>
/// 获取在线玩家
/// </summary>
/// <returns></returns>
public List<ClientInfo> GetOnlineClientList()
{
return ClientList.Where(w => w.IsOffline == false).ToList();
}
/// <summary>
/// 设置玩家离线
/// </summary>
/// <param name="sk"></param>
public void SetClientOfflineForSocket(Socket sk)
{
if (!_DictSocketClient.ContainsKey(sk))
return;
Console.WriteLine("标记玩家UID" + _DictSocketClient[sk].UID + "为离线");
_DictSocketClient[sk].IsOffline = true;
_DictSocketClient[sk].LogOutDT = DateTime.Now;
}
public void RemoveClientForSocket(Socket sk)
{
if (!_DictSocketClient.ContainsKey(sk))
return;
RemoveClient(_DictSocketClient[sk]);
}
#endregion
public void ClientSendALL(int CMDID, int ERRCODE, byte[] data)
{
ClientSend(ClientList, CMDID, ERRCODE, data);
}
/// <summary>
/// 给一组用户发送数据
/// </summary>
/// <param name="_toclientlist"></param>
/// <param name="CMDID"></param>
/// <param name="ERRCODE"></param>
/// <param name="data"></param>
public void ClientSend(List<ClientInfo> _toclientlist, int CMDID, int ERRCODE, byte[] data)
{
for (int i = 0; i < _toclientlist.Count(); i++)
{
if (_toclientlist[i] == null || _toclientlist[i].IsOffline)
continue;
ServerManager.g_SocketMgr.SendToSocket(_toclientlist[i]._socket, CMDID, ERRCODE, data);
}
}
public void ClientSend(Socket _socket, int CMDID, int ERRCODE, byte[] data)
{
//Console.WriteLine("发送数据 CMDID->"+ CMDID);
ServerManager.g_SocketMgr.SendToSocket(_socket, CMDID, ERRCODE, data);
}
/// <summary>
/// 给一个连接发送数据
/// </summary>
/// <param name="_c"></param>
/// <param name="CMDID"></param>
/// <param name="ERRCODE"></param>
/// <param name="data"></param>
public void ClientSend(ClientInfo _c, int CMDID, int ERRCODE, byte[] data)
{
if (_c == null || _c.IsOffline)
return;
ServerManager.g_SocketMgr.SendToSocket(_c._socket, CMDID, ERRCODE, data);
}
public int GetOnlineClient()
{
return ClientList.Where(w => !w.IsOffline).Count();
}
}
}

View File

@ -0,0 +1,242 @@
using AxibugProtobuf;
using ClientCore.Network;
using Google.Protobuf;
using NoSugarNet.ServerCore.Common;
using ServerCore.Common;
using ServerCore.NetWork;
using System.Net.Sockets;
namespace ServerCore.Manager
{
public class LocalClientManager
{
struct TunnelClientData
{
public string IP;
public ushort Port;
}
Dictionary<byte, TunnelClientData> mDictTunnelID2Cfg = new Dictionary<byte, TunnelClientData>();
Dictionary<long, Dictionary<byte, ServerLocalClient>> mDictUid2ServerLocalClients = new Dictionary<long, Dictionary<byte, ServerLocalClient>>();
CompressAdapter mCompressAdapter;
public LocalClientManager()
{
//初始化压缩适配器暂时使用0代表压缩类型
mCompressAdapter = new CompressAdapter(0);
//注册网络消息
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelC2SConnect, Recive_TunnelC2SConnect);
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelC2SDisconnect, Recive_TunnelC2SDisconnect);
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelC2SData, Recive_TunnelC2SData);
}
#region
/// <summary>
/// 追加连接
/// </summary>
/// <param name="uid"></param>
/// <param name="tunnelId"></param>
/// <param name="serverClient"></param>
void AddServerLocalClient(long uid, byte tunnelId, ServerLocalClient serverClient)
{
lock (mDictUid2ServerLocalClients)
{
if (!mDictUid2ServerLocalClients.ContainsKey(uid))
mDictUid2ServerLocalClients[uid] = new Dictionary<byte, ServerLocalClient>();
mDictUid2ServerLocalClients[uid][tunnelId] = serverClient;
}
}
/// <summary>
/// 删除连接
/// </summary>
/// <param name="uid"></param>
/// <param name="tunnelId"></param>
void RemoveServerLocalClient(long uid, byte tunnelId)
{
lock (mDictUid2ServerLocalClients)
{
if (!mDictUid2ServerLocalClients.ContainsKey(uid))
return;
if (!mDictUid2ServerLocalClients[uid].ContainsKey(tunnelId))
return;
mDictUid2ServerLocalClients[uid].Remove(tunnelId);
if (mDictUid2ServerLocalClients[uid].Count < 1)
mDictUid2ServerLocalClients.Remove(uid);
}
}
bool GetServerLocalClient(long uid, byte tunnelId,out ServerLocalClient serverLocalClient)
{
serverLocalClient = null;
if (!mDictUid2ServerLocalClients.ContainsKey(uid))
return false;
if (!mDictUid2ServerLocalClients[uid].ContainsKey(tunnelId))
return false;
serverLocalClient = mDictUid2ServerLocalClients[uid][tunnelId];
return true;
}
#endregion
#region
public void Recive_TunnelC2SConnect(Socket sk, byte[] reqData)
{
ClientInfo _c = ServerManager.g_ClientMgr.GetClientForSocket(sk);
ServerManager.g_Log.Debug("OnTunnelC2SConnect");
Protobuf_C2S_Connect msg = ProtoBufHelper.DeSerizlize<Protobuf_C2S_Connect>(reqData);
OnClientLocalConnect(_c.UID, (byte)msg.TunnelID);
}
public void Recive_TunnelC2SDisconnect(Socket sk, byte[] reqData)
{
ClientInfo _c = ServerManager.g_ClientMgr.GetClientForSocket(sk);
ServerManager.g_Log.Debug("Recive_TunnelC2SDisconnect");
Protobuf_C2S_Disconnect msg = ProtoBufHelper.DeSerizlize<Protobuf_C2S_Disconnect>(reqData);
OnClientLocalDisconnect(_c.UID, (byte)msg.TunnelID);
}
public void Recive_TunnelC2SData(Socket sk, byte[] reqData)
{
ClientInfo _c = ServerManager.g_ClientMgr.GetClientForSocket(sk);
ServerManager.g_Log.Debug("OnTunnelC2SData");
Protobuf_C2S_DATA msg = ProtoBufHelper.DeSerizlize<Protobuf_C2S_DATA>(reqData);
OnClientTunnelDataCallBack(_c.UID, (byte)msg.TunnelID, msg.HunterNetCoreData.ToArray());
}
#endregion
#region
/// <summary>
/// 当客户端本地端口连接
/// </summary>
/// <param name="uid"></param>
/// <param name="tunnelId"></param>
void OnClientLocalConnect(long uid, byte tunnelId)
{
if (!ServerManager.g_ClientMgr.GetClientByUID(uid, out ClientInfo client))
return;
if (!mDictTunnelID2Cfg.ContainsKey(tunnelId))
return;
//开一个线程去建立连接
Thread thread = new Thread(() =>
{
//服务器本地局域网连接指定端口
TunnelClientData tunnelDataCfg = mDictTunnelID2Cfg[tunnelId];
ServerLocalClient serverLocalClient = new ServerLocalClient(tunnelId);
//连接成功
if (!serverLocalClient.Init(tunnelDataCfg.IP, tunnelDataCfg.Port))
{
//连接失败
//TODO告知客户端连接失败
}
});
thread.Start();
}
/// <summary>
/// 当客户端本地端口连接断开
/// </summary>
/// <param name="uid"></param>
/// <param name="tunnelId"></param>
void OnClientLocalDisconnect(long uid, byte tunnelId)
{
if (!ServerManager.g_ClientMgr.GetClientByUID(uid, out ClientInfo client))
return;
//隧道ID定位投递服务端本地连接
if (!GetServerLocalClient(uid, tunnelId, out ServerLocalClient serverLocalClient))
return;
//清楚服务器数据
RemoveServerLocalClient(uid, tunnelId);
//断开服务端本地客户端连接
serverLocalClient.CloseConntect();
}
/// <summary>
/// 当服务端本地端口连接
/// </summary>
/// <param name="uid"></param>
/// <param name="tunnelId"></param>
public void OnServerLocalConnect(long uid, byte tunnelId, ServerLocalClient serverLocalClient)
{
if (!ServerManager.g_ClientMgr.GetClientByUID(uid, out ClientInfo client))
return;
//添加到服务端本地连接列表
AddServerLocalClient(uid, tunnelId, serverLocalClient);
byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_S2C_Connect()
{
TunnelID = tunnelId,
});
//发送给客户端,指定服务端本地端口已连接
ServerManager.g_ClientMgr.ClientSend(client, (int)CommandID.CmdTunnelS2CConnect, (int)ErrorCode.ErrorOk, respData);
}
/// <summary>
/// 当服务端本地端口连接断开
/// </summary>
/// <param name="uid"></param>
/// <param name="tunnelId"></param>
public void OnServerLocalDisconnect(long uid, byte tunnelId, ServerLocalClient serverLocalClient)
{
if (!ServerManager.g_ClientMgr.GetClientByUID(uid, out ClientInfo client))
return;
//添加到服务端本地连接列表
RemoveServerLocalClient(uid, tunnelId);
byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_S2C_Disconnect()
{
TunnelID = tunnelId,
});
//发送给客户端,指定服务端本地端口连接已断开
ServerManager.g_ClientMgr.ClientSend(client, (int)CommandID.CmdTunnelS2CDisconnect, (int)ErrorCode.ErrorOk, respData);
}
#endregion
#region
/// <summary>
/// 来自服务端本地连接投递的Tunnel数据
/// </summary>
/// <param name="uid"></param>
/// <param name="tunnelId"></param>
/// <param name="data"></param>
public void OnServerLocalDataCallBack(long uid, byte tunnelId, byte[] data)
{
if (!ServerManager.g_ClientMgr.GetClientByUID(uid, out ClientInfo client))
return;
//压缩
data = mCompressAdapter.Compress(data);
byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_C2S_DATA()
{
TunnelID = tunnelId,
HunterNetCoreData = ByteString.CopyFrom(data)
});
//发送给客户端指定客户端本地隧道ID
ServerManager.g_ClientMgr.ClientSend(client, (int)CommandID.CmdTunnelS2CData, (int)ErrorCode.ErrorOk, respData);
}
/// <summary>
/// 来自客户端本地连接投递的Tunnel数据
/// </summary>
/// <param name="uid"></param>
/// <param name="tunnelId"></param>
/// <param name="data"></param>
public void OnClientTunnelDataCallBack(long uid, byte tunnelId, byte[] data)
{
//隧道ID定位投递服务端本地连接
if (!GetServerLocalClient(uid, tunnelId, out ServerLocalClient serverLocalClient))
return;
//解压
data = mCompressAdapter.Decompress(data);
//发送给对应服务端本地连接数据
serverLocalClient.SendToServer(mCompressAdapter.Decompress(data));
}
#endregion
}
}

View File

@ -0,0 +1,20 @@
namespace ServerCore.Manager
{
public class LogManager
{
public void Debug(string str)
{
Console.WriteLine(str);
}
public void Warning(string str)
{
Console.WriteLine(str);
}
public void Error(string str)
{
Console.WriteLine(str);
}
}
}

View File

@ -0,0 +1,32 @@
using AxibugProtobuf;
using ServerCore.Common;
using ServerCore.NetWork;
using System.Net.Sockets;
namespace ServerCore.Manager
{
public class LoginManager
{
public LoginManager()
{
NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdLogin, UserLogin);
}
public void UserLogin(Socket _socket, byte[] reqData)
{
ServerManager.g_Log.Debug("收到新的登录请求");
Protobuf_Login msg = ProtoBufHelper.DeSerizlize<Protobuf_Login>(reqData);
ClientInfo cinfo = ServerManager.g_ClientMgr.JoinNewClient(msg, _socket);
byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_Login_RESP()
{
Status = LoginResultStatus.Ok,
RegDate = "",
LastLoginDate = "",
Token = ""
});
ServerManager.g_ClientMgr.ClientSend(cinfo, (int)CommandID.CmdLogin, (int)ErrorCode.ErrorOk, respData);
}
}
}

View File

@ -0,0 +1,76 @@
using HaoYueNet.ClientNetwork;
using ServerCore.Manager;
namespace ClientCore.Network
{
/// <summary>
/// 继承网络库,以支持网络功能
/// </summary>
public class ServerLocalClient : NetworkHelperCore_SourceMode
{
public long mUID;
public byte mTunnelID;
public ServerLocalClient(byte TunnelID)
{
mTunnelID = TunnelID;
//指定接收服务器数据事件
OnReceiveData += GetDataCallBack;
//断开连接
OnClose += OnConnectClose;
OnConnected += NetworkConnected;
//网络库调试信息输出事件,用于打印网络内容
OnLogOut += NetworkDeBugLog;
}
public void NetworkConnected(bool IsConnect)
{
NetworkDeBugLog($"NetworkConnected:{IsConnect}");
if (IsConnect)
{
ServerManager.g_Local.OnServerLocalConnect(mUID, mTunnelID,this);
}
else
{
//连接失败
NetworkDeBugLog("连接失败!");
}
}
public void NetworkDeBugLog(string str)
{
//用于Unity内的输出
//Debug.Log("NetCoreDebug >> "+str);
Console.WriteLine("NetCoreDebug >> " + str);
}
/// <summary>
/// 接受包回调
/// </summary>
/// <param name="CMDID">协议ID</param>
/// <param name="ERRCODE">错误编号</param>
/// <param name="data">业务数据</param>
public void GetDataCallBack(byte[] data)
{
NetworkDeBugLog("收到消息 数据长度=>" + data.Length);
try
{
//抛出网络数据
ServerManager.g_Local.OnServerLocalDataCallBack(mUID, mTunnelID, data);
}
catch (Exception ex)
{
NetworkDeBugLog("逻辑处理错误:" + ex.ToString());
}
}
/// <summary>
/// 关闭连接
/// </summary>
public void OnConnectClose()
{
NetworkDeBugLog("OnConnectClose");
ServerManager.g_Local.OnServerLocalDisconnect(mUID, mTunnelID,this);
}
}
}

View File

@ -0,0 +1,29 @@
using ServerCore.NetWork;
using System.Net;
namespace ServerCore.Manager
{
public static class ServerManager
{
public static ClientManager g_ClientMgr;
public static LogManager g_Log;
public static LoginManager g_Login;
public static ChatManager g_Chat;
public static LocalClientManager g_Local;
public static IOCPNetWork g_SocketMgr;
public static void InitServer(int port)
{
g_ClientMgr = new ClientManager();
g_ClientMgr.Init(45000, 120);
g_Log = new LogManager();
g_Login = new LoginManager();
g_Chat = new ChatManager();
g_Local = new LocalClientManager();
g_SocketMgr = new IOCPNetWork(1024, 1024);
g_SocketMgr.Init();
g_SocketMgr.Start(new IPEndPoint(IPAddress.Any.Address, port));
Console.WriteLine("Succeed!");
}
}
}

View File

@ -0,0 +1,64 @@
using HaoYueNet.ServerNetwork;
using ServerCore.Manager;
using System.Net.Sockets;
namespace ServerCore.NetWork
{
public class IOCPNetWork : TcpSaeaServer
{
public IOCPNetWork(int numConnections, int receiveBufferSize)
: base(numConnections, receiveBufferSize)
{
OnClientNumberChange += ClientNumberChange;
OnReceive += ReceiveData;
OnDisconnected += OnDisconnect;
OnNetLog += OnShowNetLog;
}
private void ClientNumberChange(int num, AsyncUserToken token)
{
Console.WriteLine("Client数发生变化");
}
/// <summary>
/// 接受包回调
/// </summary>
/// <param name="CMDID">协议ID</param>
/// <param name="ERRCODE">错误编号</param>
/// <param name="data">业务数据</param>
private void ReceiveData(AsyncUserToken token, int CMDID, byte[] data)
{
DataCallBack(token.Socket, CMDID, data);
}
public void DataCallBack(Socket sk, int CMDID, byte[] data)
{
ServerManager.g_Log.Debug("收到消息 CMDID =>" + CMDID + " 数据长度=>" + data.Length);
try
{
//抛出网络数据
NetMsg.Instance.PostNetMsgEvent(CMDID, sk, data);
}
catch (Exception ex)
{
Console.WriteLine("逻辑处理错误:" + ex.ToString());
}
}
/// <summary>
/// 断开连接
/// </summary>
/// <param name="sk"></param>
public void OnDisconnect(AsyncUserToken token)
{
Console.WriteLine("断开连接");
ServerManager.g_ClientMgr.SetClientOfflineForSocket(token.Socket);
}
public void OnShowNetLog(string msg)
{
ServerManager.g_Log.Debug(msg);
}
}
}

View File

@ -0,0 +1,97 @@
using ServerCore.Manager;
using System.Net.Sockets;
namespace ServerCore.NetWork
{
public class NetMsg
{
private static NetMsg instance = new NetMsg();
public static NetMsg Instance { get { return instance; } }
private Dictionary<int, List<Delegate>> netEventDic = new Dictionary<int, List<Delegate>>(128);
private NetMsg() { }
#region RegisterMsgEvent
public void RegNetMsgEvent(int cmd, Action<Socket, byte[]> callback)
{
InterRegNetMsgEvent(cmd, callback);
}
private void InterRegNetMsgEvent(int cmd, Delegate callback)
{
if (netEventDic.ContainsKey(cmd))
{
if (netEventDic[cmd].IndexOf(callback) < 0)
{
netEventDic[cmd].Add(callback);
}
}
else
{
netEventDic.Add(cmd, new List<Delegate>() { callback });
}
}
#endregion
#region UnregisterCMD
public void UnregisterCMD(int cmd, Action<Socket, byte[]> callback)
{
Delegate tempDelegate = callback;
InterUnregisterCMD(cmd, tempDelegate);
}
private void InterUnregisterCMD(int cmd, Delegate callback)
{
if (netEventDic.ContainsKey(cmd))
{
netEventDic[cmd].Remove(callback);
if (netEventDic[cmd].Count == 0) netEventDic.Remove(cmd);
}
}
#endregion
#region PostEvent
public void PostNetMsgEvent(int cmd, Socket arg1, byte[] arg2)
{
List<Delegate> eventList = GetNetEventDicList(cmd);
if (eventList != null)
{
foreach (Delegate callback in eventList)
{
try
{
((Action<Socket, byte[]>)callback)(arg1, arg2);
}
catch (Exception e)
{
ServerManager.g_Log.Error(e.Message);
}
}
}
}
#endregion
/// <summary>
/// 获取所有事件
/// </summary>
/// <param name="cmd"></param>
/// <returns></returns>
private List<Delegate> GetNetEventDicList(int cmd)
{
if (netEventDic.ContainsKey(cmd))
{
List<Delegate> tempList = netEventDic[cmd];
if (null != tempList)
{
return tempList;
}
}
return null;
}
}
}

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Reference Include="Google.Protobuf">
<HintPath>..\Lib\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="HaoYueNet.ServerNetwork">
<HintPath>..\Lib\HaoYueNet.ServerNetwork.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

30
NoSugarNet.sln Normal file
View File

@ -0,0 +1,30 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34031.279
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lib", "Lib", "{EDA9D3FD-1A72-434D-81F6-B1B420406D20}"
ProjectSection(SolutionItems) = preProject
Lib\HaoYueNet.ServerNetwork.dll = Lib\HaoYueNet.ServerNetwork.dll
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoSugarNet.ServerCore", "NoSugarNet.ServerCore\NoSugarNet.ServerCore.csproj", "{25FB6F12-4619-4D2C-8FC1-70AAAA8AD100}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{25FB6F12-4619-4D2C-8FC1-70AAAA8AD100}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{25FB6F12-4619-4D2C-8FC1-70AAAA8AD100}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25FB6F12-4619-4D2C-8FC1-70AAAA8AD100}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25FB6F12-4619-4D2C-8FC1-70AAAA8AD100}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {637DC2BB-F9BB-41A2-ADC0-B41B871F66DE}
EndGlobalSection
EndGlobal

17
ProtobufCore/build_cs.bat Normal file
View File

@ -0,0 +1,17 @@
@echo off
set "PROTOC_EXE=%cd%\protoc.exe"
set "WORK_DIR=%cd%\proto"
set "CS_OUT_PATH=%cd%\out\CS"
echo "==>>buildStart"
for /f "delims=" %%i in ('dir /b proto "proto/*.proto"') do (
echo build file:%%%i
%PROTOC_EXE% --proto_path="%WORK_DIR%" --csharp_out="%CS_OUT_PATH%" "%WORK_DIR%\%%i"
)
echo "==>>build finish"
echo "==>>copy cs"
::copy %cd%\out\CS\ ..\Project2\Assets\Scripts\HotFix\ProtoBuf\
pause

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
syntax = "proto3";
package AxibugProtobuf;
option optimize_for = SPEED;
enum CommandID
{
CMD_DEFAUL = 0;//使
CMD_LOGIN = 2001; // | Protobuf_Login | Protobuf_Login_RESP
CMD_CHATMSG = 4001; //广 | Protobuf_ChatMsg | Protobuf_ChatMsg_RESP
CMD_TUNNEL_C2S_CONNECT = 5000; // Protobuf_C2S_Connect
CMD_TUNNEL_S2C_CONNECT = 5001; // Protobuf_S2C_Connect
CMD_TUNNEL_C2S_DISCONNECT = 5002; // Protobuf_C2S_Disconnect
CMD_TUNNEL_S2C_DISCONNECT = 5003; // Protobuf_S2C_Disconnect
CMD_TUNNEL_C2S_DATA = 5004; //TCP通讯数据包 Protobuf_C2S_DATA
CMD_TUNNEL_S2C_DATA = 5005; //TCP通讯数据包 Protobuf_S2C_DATA
}
enum ErrorCode
{
ERROR_DEFAUL = 0;//使
ERROR_OK = 1; //
}
enum LoginType
{
BaseDefault = 0;//使
HaoYueAuth = 1;
BF3 = 3;
BF4 = 4;
}
enum DeviceType
{
DeviceType_Default = 0;//使
PC = 1;
Android = 2;
IOS = 3;
PSV = 4;
}
enum LoginResultStatus
{
LoginResultStatus_BaseDefault = 0;//使
OK = 1;
AccountErr = 2;
}
//
message Protobuf_Login
{
LoginType loginType = 1;// [0] [3] BF3 [4] BF4
DeviceType deviceType = 2;// [0]PC [1]AndroidPad预留 [3]IPad预留
string Account = 3;//
string Password = 4;//
}
//
message Protobuf_Login_RESP
{
string Token = 1;//
string LastLoginDate = 2;//
string RegDate = 3;//
LoginResultStatus Status = 4;// [1][0]
}
//
message Protobuf_ChatMsg
{
string ChatMsg = 1;//
}
//
message Protobuf_ChatMsg_RESP
{
string NickName = 1;//
string ChatMsg = 2;//
int64 Date = 3;//
}
message Protobuf_C2S_Connect
{
int32 TunnelID = 1;//TunnelID
}
message Protobuf_S2C_Connect
{
int32 TunnelID = 1;//TunnelID
}
message Protobuf_C2S_Disconnect
{
int32 TunnelID = 1;//TunnelID
}
message Protobuf_S2C_Disconnect
{
int32 TunnelID = 1;//TunnelID
}
message Protobuf_C2S_DATA
{
int32 TunnelID = 1;//TunnelID
bytes HunterNetCore_Data = 2;
}
message Protobuf_S2C_DATA
{
int32 TunnelID = 1;//TunnelID
bytes HunterNetCore_Data = 2;
}

BIN
ProtobufCore/protoc.exe Normal file

Binary file not shown.