配色: 字号:
UnitySocket服务器(客户端)通用框架
2023-07-19 | 阅:  转:  |  分享 
  
UnitySocket服务器(客户端)通?框架

通?服务端框架,具有粘包半包处理、协议解析等功能,服务端使?多路复?,单进程单线程

客户端

?络相关代码

using Assets.Scripts.Net.Proto;

using System;

using System.Collections;

using System.Collections.Generic;

using System.Net.Sockets;

using System.Text;

using UnityEngine;

public delegate void EventListener(string err);

public delegate void MsgListener(MsgBase msg);

public static class NetManager

{

//是否启??跳

public static bool isUsePing = true;

//?跳间隔时间

public static int pingInterval = 30;

//上?次发送Ping时间

public static float lastPingTime = 0;

//上?次接收Pong时间

public static float lastPongTime = 0;

//消息监听字典

private static Dictionary MsgListenerDic = new Dictionary();

//事件监听字典

private static Dictionary EventListenerDic = new Dictionary();

//是否正在断开连接

private static bool isClosing;

//是否正在连接

private static bool isConnecting;

private static Socket socket;

//读取数据缓存

private static byte[] readBuff;

//数据缓存??

public static int BuffTotalCount = 2048;

//接收缓冲区的数据长度

private static int buffcount;

//发送消息缓存队列

private static Queue writeQueue;

//接收消息缓存列表

private static List msgList;

//接收消息缓存列表数量

private static int msgCount;

//每?次Update处理的消息量

readonly static int MAX_MESSAGE_FIRE = 10;

//初始化

private static void InitState()

{

//上次发送Ping时间

lastPingTime = Time.time;

//上次收到Pong时间

lastPongTime = Time.time;

isClosing = false;

socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

readBuff = new byte[BuffTotalCount];

writeQueue = new Queue();

msgList = new List();

msgCount = 0;

buffcount = 0;

if (!MsgListenerDic.ContainsKey("MsgPong"))

{

MsgListenerDic.Add("MsgPong", OnMsgPong);

}

}

}

///

///发送 Ping协议

///


private static void PingUpdate()

{

if (!isUsePing)

{

return;

}

if (socket==null||!socket.Connected)

{

return;

}

//发送 Ping

if (Time.time-lastPingTime>pingInterval)

{

MsgPing ping = new MsgPing("MsgPing");

Send(ping);

lastPingTime = Time.time;

}

if (Time.time - lastPongTime > pingInterval4)

{

socket.Close();

socket.Dispose();

}

}

private static void OnMsgPong(MsgBase msg)

{

lastPongTime = Time.time;

}

///

///连接服务器

///


/// 服务器 Ip

/// 端号

public static void Connect(string ip , int port)

{

if (socket!=null&&socket.Connected)

{

Debug.Log("已连接 ");

return;

}

if (isConnecting)

{

Debug.Log("正在连接 .....");

}

isConnecting = false;

InitState();

socket.BeginConnect(ip,port, ConnectCallBack,socket);

}

///

///断开连接

///


public static void Close()

{

if (socket==null||!socket.Connected)

{

Debug.Log("未能断开连接,原因:未连接服务器 ");

return;

}

if (isConnecting)

{

Debug.Log("未能断开连接,原因:未连接服务器 ");

return;

}

if (writeQueue.Count>0)

{

isClosing = true;

}

else

{

socket.Close();

socket.Close();

FireEvent(NetEvent.Close,"");

}

}

///

///发送消息

///


public static void Send(MsgBase msg)

{

if (socket==null||!socket.Connected)

{

Debug.Log("发送失败,未连接服务器!");

return;

}

if (isConnecting)

{

Debug.Log("发送失败,正在连接服务器。。。。");

return;

}

if (isClosing)

{

Debug.Log("发送失败,正在断开连接。。。。");

return;

}

//数据编码

byte[] nameBytes = MsgBase.EncodeProtoName(msg);

byte[] bodyBytes = MsgBase.Encode(msg);

int totalLen = nameBytes.Length + bodyBytes.Length;

byte[] sendBytes = new byte[totalLen + 2];

sendBytes[0] = (byte)(totalLen % 256);

sendBytes[1] = (byte)(totalLen / 256);

Array.Copy(nameBytes, 0, sendBytes, 2, nameBytes.Length);

Array.Copy(bodyBytes,0,sendBytes, nameBytes.Length+2,bodyBytes.Length);

int count = 0;

lock (writeQueue)

{

writeQueue.Enqueue(sendBytes);

count = writeQueue.Count;

}

if (count>0)

{

socket.BeginSend(sendBytes,0,sendBytes.Length,0, SendCallBack,socket);

}

}

///

///更新消息

///


public static void MsgUpdate()

{

if (msgCount == 0)

{

return;

}

for (int i = 0; i < MAX_MESSAGE_FIRE; i++)

{

//获取第?条消息

MsgBase msg = null;

lock (msgList)

{

if (msgList.Count>0)

{

msg = msgList[0];

msgList.RemoveAt(0);

msgCount--;

}

}

if (msg!=null)

{

FireMsg(msg.protoName,msg);

}

else

{

break;

break;

}

}

}

///

///发送消息回调

///


///

private static void SendCallBack(IAsyncResult asyncResult)

{

Socket socket = asyncResult.AsyncState as Socket;

if (socket==null||!socket.Connected)

{

return;

}

//EndSend

int count = socket.EndSend(asyncResult);

//取出队列第?个消息

byte[] ba;

lock (writeQueue)

{

ba = writeQueue.Peek();

}

int idx = count;

if (ba.Length == count)

{

idx = 0;

lock (writeQueue)

{

writeQueue.Dequeue();

ba = writeQueue.Count > 0 ? writeQueue.Peek() : null;

}

}

if (ba != null)

{

socket.BeginSend(ba,idx,ba.Length,0,SendCallBack,socket);

}

else if(isClosing)

{

socket.Close();

}

}

//连接回调

private static void ConnectCallBack(IAsyncResult asyncResult)

{

try

{

Socket socket = asyncResult.AsyncState as Socket;

socket.EndConnect(asyncResult);

isConnecting = false;

FireEvent(NetEvent.ConnectSucc,"");

socket.BeginReceive(readBuff,buffcount,BuffTotalCount-buffcount,0, ReciveCallBack,socket);

}catch(SocketException ex)

{

isConnecting = false;

Debug.Log("连接失败:"+ex.ToString());

FireEvent(NetEvent.ConnectFail,"");

}

}

private static void ReciveCallBack(IAsyncResult asyncResult)

{

Socket socket = asyncResult.AsyncState as Socket;

int count = socket.EndReceive(asyncResult);

buffcount += count;

OnReciveData();

//继续接收数据

socket.BeginReceive(readBuff,buffcount,BuffTotalCount- buffcount, 0,ReciveCallBack,socket);

}

///

///处理缓冲区消息(解决粘包问题)

///


private static void OnReciveData()

{

{

//消息不?够长

if (buffcount <= 2)

{

return;

}

Int16 bodyLen = (Int16)(readBuff[1] << 8 | readBuff[0]);

if (buffcount
{

return;

}

//string s = Encoding.UTF8.GetString(readBuff,2,bodyLen);

int nameCount = 0;

int start = 2 + bodyLen;

int count = buffcount - start;

//解析协议名

string protoName = MsgBase.DecodeProtoName(readBuff,2,out nameCount);

if (protoName=="")

{

Debug.Log("OnReciveData MsgBase.DecodeProtoName:Fail");

return;

}

int readIdx = 2 + nameCount;

MsgBase msgBase = MsgBase.Decode(protoName,readBuff,readIdx,bodyLen-nameCount);

//添加消息

lock (msgList)

{

msgList.Add(msgBase);

}

msgCount++;

Array.Copy(readBuff,start,readBuff,0,count);

buffcount -= start;

OnReciveData();

}

//分发消息

private static void FireEvent(NetEvent netEvent,string err)

{

if (EventListenerDic.ContainsKey(netEvent)&& EventListenerDic[netEvent]!=null)

{

EventListenerDic[netEvent](err);

}

}

///

///添加监听事件

///


///

///

public static void AddListener(NetEvent netEvent,EventListener listener)

{

if (EventListenerDic.ContainsKey(netEvent))

{

EventListenerDic[netEvent] += listener;

}

else

{

EventListenerDic.Add(netEvent,listener);

}

}

///

///移除监听事件

///


///

///

public static void RemoveListener(NetEvent netEvent, EventListener listener)

{

if (EventListenerDic.ContainsKey(netEvent))

{

if (EventListenerDic[netEvent]!=null)

{

EventListenerDic[netEvent] -= listener;

}

else

{

{

EventListenerDic.Remove(netEvent);

}

}

}

///

///添加消息监听

///


/// 消息名称

/// 回调函数

public static void AddMsgListener(string msgName , MsgListener msgListener)

{

if (MsgListenerDic.ContainsKey(msgName))

{

MsgListenerDic[msgName] += msgListener;

}

else

{

MsgListenerDic[msgName] = msgListener;

}

}

///

///移除消息监听

///


/// 消息类型名称

/// 回调函数

public static void RemoveMsgListener(string msgName,MsgListener msgListener)

{

if (MsgListenerDic.ContainsKey(msgName))

{

if (MsgListenerDic[msgName]!=null)

{

MsgListenerDic[msgName] -= msgListener;

}

else

{

MsgListenerDic.Remove(msgName);

}

}

}

///

///分发消息

///


/// 消息类型

/// 消息类

private static void FireMsg(string msgName,MsgBase msg)

{

if (MsgListenerDic.ContainsKey(msgName)&& MsgListenerDic[msgName]!=null)

{

MsgListenerDic[msgName](msg);

}

}

public static void Update()

{

MsgUpdate();

PingUpdate();

}

}

public enum NetEvent

{

ConnectSucc = 1,

ConnectFail = 2,

Close = 3,

}

客户端MsgBa se 协议基类

using System;

using System.Collections;

using System.Collections;

using System.Collections.Generic;

using System.Text;

using UnityEngine;

using Assets.Scripts.Models;

[System.Serializable]

public class MsgBase

{

//协议名

public string protoName="";

public MsgBase(string protoName)

{

this.protoName = protoName;

}

public static byte[] Encode(MsgBase msgBase)

{

string json = JsonUtility.ToJson(msgBase);

return Encoding.UTF8.GetBytes(json);

}

public static MsgBase Decode(string protoName,byte[] bytes,int offset,int count)

{

string json = Encoding.UTF8.GetString(bytes,offset,count);

string typeName = "Assets.Scripts.Net.Proto." + protoName;

MsgBase msg = (MsgBase)JsonUtility.FromJson(json,Type.GetType(typeName));

return msg;

}

///

///编码协议名

///


/// 协议

///

public static byte[] EncodeProtoName(MsgBase msg)

{

byte[] nameBytes = Encoding.UTF8.GetBytes(msg.protoName);

int nameLen = nameBytes.Length;

byte[] ret = new byte[nameLen+2];

ret[0] = (byte)(nameLen % 256);

ret[1] = (byte)(nameLen / 256);

Array.Copy(nameBytes,0,ret,2,nameLen);

return ret;

}

///

///解码协议名

///


///

///

///

///

public static string DecodeProtoName(byte[] bytes,int offset,out int count)

{

count = 0;

if (offset+2>bytes.Length)

{

return "";

}

//读取长度

Int16 len = (Int16)(bytes[offset + 1] << 8 | bytes[offset]);

if (len<=0)

{

count = 2;

return "";

}

if (offset+2+len>bytes.Length)

{

return "";

}

count = 2 + len;

string name = Encoding.UTF8.GetString(bytes,offset+2,len);

return name;

}

}

服务端NetManager

using System;

using System.Collections.Generic;

using System.Net;

using System.Net.Sockets;

using System.Reflection;

using System.Text;

namespace SeverManager

{

public class NetManager

{

//监听Socket

static Socket listenfd;

//客户端Socket和状态信息

public static Dictionary clients = new Dictionary();

//Select的检查列表

public static List checkRead = new List();

//客户端ping间隔时间

public static int pingInterval;

public static bool isUsePing = true;

///

///启动服务器

///


///

public static void StartLoop(int port,bool isPing=true,int pingTime = 30)

{

pingInterval = 30;

isUsePing = isPing;

pingInterval = pingTime;

listenfd = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

IPAddress ip = IPAddress.Parse("127.0.0.1");

IPEndPoint endPoint = new IPEndPoint(ip,port);

listenfd.Bind(endPoint);

listenfd.Listen(0);

Console.WriteLine("服务器启动成功:"+DateTime.Now.ToString());

while (true)

{

ResetCheckRead();

Socket.Select(checkRead,null,null,1000);

for (int i = checkRead.Count-1; i >=0; i--)

{

Socket item = checkRead[i];

if (item==listenfd)

if (item==listenfd)

{

//服务端收到请求连接

ReadListenfd(listenfd);

}

else

{

//客户端发来消息

ReadClientfd(item);

}

}

OnTimer();

}



}

public static void ResetCheckRead()

{

checkRead.Clear();

checkRead.Add(listenfd);

foreach (ClientState item in clients.Values)

{

checkRead.Add(item.socket);

}

}

//读取Listenfd

public static void ReadListenfd(Socket listenfd)

{

try

{

Socket clientfd = listenfd.Accept();

Console.WriteLine("Accept :"+clientfd.RemoteEndPoint.ToString());

ClientState state = new ClientState();

state.socket = clientfd;

state.lastPingTime = GetTimeSpan();

clients.Add(clientfd,state);

}

catch (Exception ex)

{

Console.WriteLine("Accept Fail:" + ex.ToString());

}

}

//读取Clientfd

public static void ReadClientfd(Socket clientfd)

{

ClientState state = clients[clientfd];

try

{

int count = clientfd.Receive(state.readBuff,state.buffCount,state.capacity-state.buffCount,0);

state.buffCount += count;

if (count<=0)

{

//TODO:关闭连接分发事件

Close(state);

}



}

catch (SocketException ex)

{

Console.WriteLine("Recive Exception:"+ex.ToString());

Close(state);

}

OnReciveData(state);

}



///

///解析协议(处理粘包半包长度信息法)

///


///

private static void OnReciveData(ClientState state)

{

Console.WriteLine("Recv:"+Encoding.UTF8.GetString(state.readBuff));

byte[] readBuff = state.readBuff;

byte[] readBuff = state.readBuff;

if (state.buffCount<=2)

{

return;

}

Int16 bodyLen = Convert.ToInt16(readBuff[1] << 8 | readBuff[0]);

if (state.buffCount
{

return;

}

int protoNameLen = 0;

string protoName = MsgBase.DecodeProtoName(readBuff,2,out protoNameLen);

MsgBase msg = MsgBase.Decode(protoName,readBuff,2+protoNameLen, bodyLen- protoNameLen);

//处理消息

MethodInfo method = typeof(MsgHandler).GetMethod("On"+protoName);

if (method!=null)

{

object[] param = { state, msg };

method.Invoke(null,param);

}

else

{

Console.WriteLine("OnReciveData Invoke Fail:"+protoName);

}

int start = 2+bodyLen;

int count = state.buffCount - start;

Array.Copy(state.readBuff,start,state.readBuff,0,count);

state.buffCount -= start;

OnReciveData(state);

}

///

///关闭连接

///


public static void Close(ClientState state)

{

MethodInfo method = typeof(EventHandler).GetMethod("OnDisconnect");

if (method==null)

{

Console.WriteLine("Close EventHandler Fun null:OnDisconnect");

}

else

{

object[] prarm = { state };

method.Invoke(null, prarm);

}

state.socket.Close();

clients.Remove(state.socket);

state.socket.Dispose();

}

///

///发送消息

///


///

///

public static void SendMsg(ClientState state , MsgBase msg)

{

if (state.socket==null||!state.socket.Connected)

{

return;

}

byte[] protoBytes = MsgBase.EncodeProtoName(msg.protoName);

byte[] bodyBytes = MsgBase.Encode(msg);

byte[] sendData = new byte[protoBytes.Length+ bodyBytes.Length+2];

int totalLen = protoBytes.Length + bodyBytes.Length;

sendData[0] = Convert.ToByte(totalLen % 256);

sendData[1] = Convert.ToByte(totalLen / 256);

Array.Copy(protoBytes,0,sendData,2,protoBytes.Length);

Array.Copy(bodyBytes, 0, sendData, protoBytes.Length+2, bodyBytes.Length);

lock (state.sendQueue)

{

state.sendQueue.Enqueue(sendData);

}

byte[] data = state.sendQueue.Peek();

try

{

state.socket.BeginSend(data, 0, data.Length, 0, OnSendCallBack, state.socket);

}catch(SocketException ex)

{

Console.WriteLine("SendMsg Fail:"+ex.ToString());

}



}

///

///发送消息回调

///


///

private static void OnSendCallBack(IAsyncResult asyncResult)

{

Socket socket = asyncResult.AsyncState as Socket;

ClientState state = clients[socket];

try

{

int count = socket.EndSend(asyncResult);

byte[] ba = state.sendQueue.Peek();

if (count == ba.Length)

{

lock (state.sendQueue)

{

state.sendQueue.Dequeue();

ba = state.sendQueue.Count > 0 ? state.sendQueue.Peek() : null;

}

}

if (ba!=null)

{

socket.BeginSend(ba, 0, ba.Length, 0, OnSendCallBack, socket);

}



}

catch (SocketException ex)

{

Console.WriteLine("OnSendCallBack Fail:"+ex.ToString());

}

}

///

///检测断线

///


private static void OnTimer()

{

if (!isUsePing)

{

return;

}

long nowts = GetTimeSpan();

foreach (ClientState item in clients.Values)

{

if (nowts - item.lastPingTime>pingInterval4)

{

Console.WriteLine("Ping Close:"+item.socket.RemoteEndPoint.ToString());

Close(item);

return;

}

}

}

public static long GetTimeSpan()

{

TimeSpan timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);

return Convert.ToInt64(timeSpan.TotalSeconds);

}

}

}

连接数据库 DBMananger

using System;

using System.Collections.Generic;

using System.Text;

using System.Text.RegularExpressions;

using MySql.Data.MySqlClient;

namespace SeverManager

{

public class DBManager

{

public static MySqlConnection mySql;

///

///连接数据库

///


///

///

///

///

///

///

public static bool ConnectDB(string db,string ip,int port,string user,string pw)

{

mySql = new MySqlConnection();

//连接参数

string connectStr = string.Format("Database={0};Data Source={1};Port={2};User Id={3};Password={4};", db,ip,port,user,pw);

mySql.ConnectionString = connectStr;

try

{

mySql.Open();

Console.WriteLine("【数据库】connect success!");

return true;

}

catch (Exception ex)

{

Console.WriteLine("【数据库】Connect Fail:"+ex.Message);

return false;

}

}

///

///判断是否是安全字符串

///


///

///

public static bool IsSafeString(string str)

{

if (string.IsNullOrEmpty(str))

{

return true;

}

return !Regex.IsMatch(str,@"[-|;|,|.|\/|\(|\)|\{|\}|%|@|\|!|\'']");

}

///

///判断是否存在?户

///


///

///

public static bool IsAccountExist(string col,string val)

{

//防?SQL注?

if (!DBManager.IsSafeString(val))

{

Console.WriteLine("【数据库】IsAccountExist: Id is not safe");

return false;

}

if (!DBManager.IsSafeString(col))

{

Console.WriteLine("【数据库】IsAccountExist: col is not safe");

return false;

}

//sql语句

string sqlStr = string.Format("select from account where {0} = ''{1}''", col.Trim(), val.Trim());

try

{

MySqlCommand command = new MySqlCommand(sqlStr, mySql);

MySqlDataReader dataReader = command.ExecuteReader();

bool hasRow = dataReader.HasRows;

dataReader.Close();

return hasRow;

}catch(Exception ex)

{

Console.WriteLine("【数据库】IsAccountExist ERR:"+ex.Message);

return false;

}



}

///

///注册?户

///


/// ?户信息

public static bool Register(Account account)

{

if (!IsSafeString(account.Id))

{

Console.WriteLine("【数据库】Register: Id is not safe");

return false;

}

if (!IsSafeString(account.PassWord))

{

Console.WriteLine("【数据库】Register: Password is not safe");

return false;

}

if (!IsSafeString(account.NickName))

{

Console.WriteLine("【数据库】Register: NickName is not safe");

return false;

}

if (IsAccountExist("Id",account.Id))

{

Console.WriteLine("【数据库】Register faiil:已存在?户 id:"+account.Id);

return false;

}

try

{

string s =string.Format("insert into account set Id=''{0}'',PassWord=''{1}'',NickName=''{2}'',CreateTime = ''{3}''",account.Id,account.PassWord,account.NickName,DateTime

using (MySqlCommand cmd = new MySqlCommand(s, mySql))

{

cmd.ExecuteNonQuery();

}



return true;

}

catch (Exception ex)

{

Console.WriteLine("【数据库】Register ERR:"+ex.Message);

return false;

}

}

///

///创建??信息

///


///

///

public static bool CreatePlayerData(string id)

{

if (!IsSafeString(id))

{

Console.WriteLine("【数据库】CreatePlayerData fail: Id is not safe");

return false;

}

if (!IsAccountExist("Id",id))

if (!IsAccountExist("Id",id))

{

Console.WriteLine("【数据库】CreatePlayerData fail: 不存在账号信息 "+id);

return false;

}

try

{

string s = string.Format("insert into PlayerData set PlayerId=''{0}'',Coins={1},PlayerLevel={2},PlayerDesc=''{3}''",id.Trim(),0,1,"");

using (MySqlCommand cmd = new MySqlCommand(s, mySql))

{

cmd.ExecuteNonQuery();

}

return true;

}

catch (Exception ex)

{

Console.WriteLine("【数据库】CreatePlayerData ERR:"+ ex.Message);

return false;

}

}

///

///检查?户名密码

///


///

///

///

public static bool CheckPassword(string id,string pwd)

{

if (!IsSafeString(id))

{

Console.WriteLine("【数据库】CheckPassword:id is not safe");

return false;

}

if (!IsSafeString(pwd))

{

Console.WriteLine("【数据库】CheckPassword:pwd is not safe");

return false;

}

try

{

string s = string.Format("select from Account where Id=''{0}'' and Password=''{1}''",id.Trim(),pwd.Trim());

MySqlCommand cmd = new MySqlCommand(s,mySql);

MySqlDataReader data = cmd.ExecuteReader();

bool hasrows = data.HasRows;

data.Close();

return hasrows;

}

catch (Exception ex)

{

Console.WriteLine("【数据库】CheckPassword ERR:"+ex.Message);

return false;

}

}

///

///获取玩家数据

///


/// ?户id

///

public static PlayerData GetPlayerData(string id)

{

if (!IsSafeString(id))

{

Console.WriteLine("【数据库】GetPlayerData fail:id isnot safe");

return null;

}

string s = string.Format("select from PlayerData where PlayerId = ''{0}''", id.Trim());

try

{

MySqlCommand cmd = new MySqlCommand(s,mySql);

MySqlDataReader data = cmd.ExecuteReader();

if (!data.HasRows)

{

return null;

}

}

data.Read();

string plyaerId = data["PlayerId"].ToString();

int coins = Convert.ToInt32(data["Coins"]);

int levl = Convert.ToInt32(data["PlayerLevel"]);

string playerDesc = data["PlayerDesc"].ToString();

PlayerData playerData = new PlayerData(plyaerId,coins,levl,playerDesc);

data.Close();

return playerData;

}

catch (Exception ex) {

Console.WriteLine("【数据库】GetPlayerData ERR:"+ex.Message);

return null;

}

}

///

///更新?户数据

///


///

///

public static bool UpdatePlayerData(PlayerData playerData)

{

try

{

string s = string.Format("update PlayerData set Coins = {0},PlayerLevel = {1},PlayerDesc=''{2}'' where PlayerId={3}",playerData.Coins,playerData.PlayerLevel,playerD

using (MySqlCommand cmd = new MySqlCommand(s, mySql))

{

cmd.ExecuteNonQuery();

}

return true;

}

catch (Exception ex)

{

Console.WriteLine("【数据库】UpdatePlayerData ERR:" + ex.Message) ;

return false;

}

}

}

}

??管理 PlayerManger

using System;

using System.Collections.Generic;

using System.Text;

namespace SeverManager

{

public class PlayerManager

{

private static Dictionary PlayerDic = new Dictionary();

///

///添加??

///


///

public static void AddPlayer(Player player)

{

if (!PlayerDic.ContainsKey(player.Id))

{

PlayerDic.Add(player.Id,player);

}

}

///

///移除??

///


///

public static void RemovePlayer(string id)

{

if (PlayerDic.ContainsKey(id))

{

PlayerDic.Remove(id);

}

}

///

///获取??ById

///


///

public static Player GetPlayerById(string id)

{

return PlayerDic[id];

}

///

///是否在线

///


///

///

public static bool IsOnline(string id)

{

return PlayerDic.ContainsKey(id);

}

}

}

服务端 MsgBase 协议基类服务端 MsgBase 协议基类

using System;

using System.Collections.Generic;

using System.Text;

using Newtonsoft.Json;

namespace SeverManager

{

public class MsgBase

{

public string protoName;

public MsgBase(string protoName)

{

this.protoName = protoName;

}

public static byte[] Encode(MsgBase msg)

{

byte[] bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(msg));

return bytes;

}

public static MsgBase Decode(string protoName, byte[] bytes, int offset, int count)

{

string s = Encoding.UTF8.GetString(bytes,offset,count);

Type type = Type.GetType("SeverManager." + protoName);

MsgBase msg =(MsgBase) JsonConvert.DeserializeObject(s, type);

return msg;

}

public static byte[] EncodeProtoName(string protoName)

{

byte[] nameBy = Encoding.UTF8.GetBytes(protoName);

byte[] ret = new byte[2+nameBy.Length];

ret[0] = Convert.ToByte(nameBy.Length % 256);

ret[1] = Convert.ToByte(nameBy.Length / 256);

Array.Copy(nameBy,0,ret,2,nameBy.Length);

return ret;

}

public static string DecodeProtoName(byte[] data , int offset , out int count)

{

count = 0;

if (offset+2>=data.Length)

{

return "";

}

int len = data[offset + 1] << 8 | data[offset];

if (len<=0)

{

count = 2;

return "";

}

count = len + 2;

string s = Encoding.UTF8.GetString(data,offset+2,len);

return s;

}

}

}

ClientSta te 服务端监听的客户端状态

using iTextSharp.text.pdf.qrcode;

using System;

using System.Collections.Generic;

using System.Net.Sockets;

using System.Text;

namespace SeverManager

{

public class ClientState

{

public int capacity = 1024;

public Socket socket;

public byte[] readBuff;

public int buffCount = 0;

public Queue sendQueue;

public long lastPingTime;

public Player player;

public ClientState()

{

readBuff = new byte[capacity];

sendQueue = new Queue();

}

}

}

献花(0)
+1
(本文系考试资料文...原创)