u3d局域网游戏网络(c# socket select 模型)
Posted 武装三藏
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了u3d局域网游戏网络(c# socket select 模型)相关的知识,希望对你有一定的参考价值。
之前写了一篇。
发完之后第二天实际应用到游戏之后还是发现了一些小毛病。
比如网络模块有重复使用(多对象)的情况。所以将静态类该成了普通类。
比如安卓下会有些异常出现导致游戏逻辑不正常。所以网络相关的函数有些加了try块。
然后发现写入固定ip的方式根本不适合局域网。于是加了udp做的广播系统,用以服务器和客户端查找ip。
udp广播部分和tcp不一样。因为没有连接,所以socket不需要shutdown。我在这里吃了一亏才知道。
别的没什么修改。贴上修正和扩展之后的代码。
有缘之人自取。唯一要求,如果你发现代码有错,或者有可以提升性能的地方请留言告知。
另:因为这是为局域网设计的,所以网络部分框架以及锁的应用写得很随意,如果需要扩展至千人万人级的承载,请自行修改。
基础类(base)
ClientMsgUnPack.cs 服务器tcp部分用以解包的对象
1 using UnityEngine; 2 /* 3 * 通信协议 4 * 消息头前2字节保存当前消息长度 5 * 后面跟4字节表示消息ID 6 * 再后面是消息实质内容 7 */ 8 9 namespace LanSocket 10 { 11 class ClientMsgUnPack : MsgUnPack 12 { 13 long m_UserID; 14 public ClientMsgUnPack() 15 { 16 m_UserID = -1; 17 } 18 19 public ClientMsgUnPack(byte[] mBuff, ushort len, int userID) 20 { 21 m_UserID = userID; 22 UnPack(mBuff, len); 23 } 24 25 public ClientMsgUnPack(byte[] mBuff, ushort offset, ushort len, int userID) 26 { 27 m_UserID = userID; 28 UnPack(mBuff, offset, len); 29 } 30 31 public long GetUserID() 32 { 33 return m_UserID; 34 } 35 36 public void SetUserID(long userID) 37 { 38 m_UserID = userID; 39 } 40 } 41 }
EventDispath.cs 事件分发,有两个类,分别对应服务器和客户端,主要就是参数不同
1 using UnityEngine; 2 using System.Collections; 3 using System.Collections.Generic; 4 5 delegate void ServerEventDelagate(LanSocket.ClientMsgUnPack msg); 6 7 class EventNode 8 { 9 public int m_EventID; 10 public LanSocket.ClientMsgUnPack msg; 11 } 12 13 class EventDispathBase 14 { 15 public static int g_MaxEventNum = 300; 16 } 17 18 class ServerEventDispath : EventDispathBase 19 { 20 List<ServerEventDelagate>[] m_Event; 21 Queue<EventNode> m_EventQueue; 22 public ServerEventDispath() 23 { 24 m_Event = new List<ServerEventDelagate>[g_MaxEventNum]; 25 m_EventQueue = new Queue<EventNode>(); 26 } 27 28 public void RegistEvent(int eventID, ServerEventDelagate func) 29 { 30 if(null == m_Event[eventID]) 31 { 32 m_Event[eventID] = new List<ServerEventDelagate>(); 33 } 34 m_Event[eventID].Add(func); 35 } 36 37 public void AddEvent(EventNode eventNode) 38 { 39 m_EventQueue.Enqueue(eventNode); 40 } 41 42 public void Proccess() 43 { 44 if (0 != m_EventQueue.Count) 45 { 46 EventNode mCur = m_EventQueue.Dequeue(); 47 if (null == m_Event[mCur.m_EventID]) 48 { 49 MonoBehaviour.print("event ID: "+ mCur.m_EventID+" is null"); 50 } 51 else 52 { 53 List<ServerEventDelagate> curEventDelagate = m_Event[mCur.m_EventID]; 54 for(int i = 0 ; i < curEventDelagate.Count ; ++i) 55 { 56 curEventDelagate[i](mCur.msg); 57 } 58 } 59 } 60 } 61 } 62 63 64 delegate void ClientEventDelagate(LanSocket.MsgUnPack msg); 65 class ClientEventDispath : EventDispathBase 66 { 67 List<ClientEventDelagate>[] m_Event; 68 Queue<EventNode> m_EventQueue; 69 public ClientEventDispath() 70 { 71 m_Event = new List<ClientEventDelagate>[g_MaxEventNum]; 72 m_EventQueue = new Queue<EventNode>(); 73 } 74 75 public void RegistEvent(int eventID, ClientEventDelagate func) 76 { 77 if (null == m_Event[eventID]) 78 { 79 m_Event[eventID] = new List<ClientEventDelagate>(); 80 } 81 m_Event[eventID].Add(func); 82 } 83 84 public void AddEvent(EventNode eventNode) 85 { 86 m_EventQueue.Enqueue(eventNode); 87 } 88 89 public void Proccess() 90 { 91 if (0 != m_EventQueue.Count) 92 { 93 EventNode mCur = m_EventQueue.Dequeue(); 94 if (null == m_Event[mCur.m_EventID]) 95 { 96 MonoBehaviour.print("event ID: " + mCur.m_EventID + " is null"); 97 } 98 else 99 { 100 List<ClientEventDelagate> curEventDelagate = m_Event[mCur.m_EventID]; 101 for (int i = 0; i < curEventDelagate.Count; ++i) 102 { 103 curEventDelagate[i](mCur.msg); 104 } 105 } 106 } 107 } 108 }
LanSocketBase.cs 没什么实际意义,主要就是定义一些大家都会使用到的变量等
1 using System.Threading; 2 using UnityEngine; 3 4 /* 5 *轻量级局域网服务器。 6 * 协议如下 7 * 消息头前2字节保存当前消息长度 8 * 后面跟4字节表示消息ID 9 * 再后面是消息实质内容 10 */ 11 12 namespace LanSocket 13 { 14 public class LanSocketBase 15 { 16 public static int m_MaxOnePackBuff = 1024 * 3; 17 public static int m_MaxAllBuff = 1024 * 50; 18 public static int m_HeadSize = 6; 19 protected bool m_HasInit = false; 20 protected byte[] m_OnePack; 21 protected int m_OnePackIndex; 22 private Mutex m_Mutex; 23 24 public void BaseInit() 25 { 26 m_HasInit = true; 27 m_Mutex = new Mutex(); 28 m_OnePack = new byte[m_MaxOnePackBuff+1]; 29 m_OnePackIndex = 0; 30 } 31 32 public void BaseRelease() 33 { 34 m_Mutex.Close(); 35 } 36 37 protected void Lock() 38 { 39 m_Mutex.WaitOne(); 40 //MonoBehaviour.print("Lock:" + Thread.CurrentThread.ManagedThreadId.ToString()); 41 } 42 43 protected void UnLock() 44 { 45 m_Mutex.ReleaseMutex(); 46 //MonoBehaviour.print("Unlock:" + Thread.CurrentThread.ManagedThreadId.ToString()); 47 } 48 } 49 }
MsgPack.cs 打包类,参数类型不够自行扩展
1 using UnityEngine; 2 /* 3 * 通信协议 4 * 消息头前2字节保存当前消息长度 5 * 后面跟4字节表示消息ID 6 * 再后面是消息实质内容 7 */ 8 9 namespace LanSocket 10 { 11 public class MsgPack : PackBase 12 { 13 public MsgPack() 14 { 15 m_OnePackIndex = LanSocketBase.m_HeadSize; 16 } 17 18 public void SetHead(int ID) 19 { 20 byte[] mBuff = System.BitConverter.GetBytes(ID); 21 System.Buffer.BlockCopy(mBuff, 0, m_OnePack, 2, 4); 22 } 23 24 public void PackEnd() 25 { 26 byte[] mBuff = System.BitConverter.GetBytes(m_OnePackIndex); 27 System.Buffer.BlockCopy(mBuff, 0, m_OnePack, 0, 2); 28 } 29 30 public void Packbool(bool data) 31 { 32 ushort curDatalen = 1; 33 if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff) 34 { 35 MonoBehaviour.print("Packbool() longer lager than Max buff len"); 36 return; 37 } 38 byte[] mBuff = System.BitConverter.GetBytes(data); 39 Pack(mBuff, curDatalen); 40 } 41 42 public void Pack16bit(short data) 43 { 44 ushort curDatalen = 2; 45 if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff) 46 { 47 MonoBehaviour.print("Pack16bit(short) longer lager than Max buff len"); 48 return; 49 } 50 byte[] mBuff = System.BitConverter.GetBytes(data); 51 Pack(mBuff, curDatalen); 52 } 53 public void Pack16bit(ushort data) 54 { 55 ushort curDatalen = 2; 56 if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff) 57 { 58 MonoBehaviour.print("Pack16bit(ushort) longer lager than Max buff len"); 59 return; 60 } 61 byte[] mBuff = System.BitConverter.GetBytes(data); 62 Pack(mBuff, curDatalen); 63 } 64 public void Pack32bit(int data) 65 { 66 ushort curDatalen = 4; 67 if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff) 68 { 69 MonoBehaviour.print("Pack32bit(int) longer lager than Max buff len"); 70 return; 71 } 72 byte[] mBuff = System.BitConverter.GetBytes(data); 73 Pack(mBuff, curDatalen); 74 } 75 public void Pack32bit(uint data) 76 { 77 ushort curDatalen = 4; 78 if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff) 79 { 80 MonoBehaviour.print("Pack32bit(uint) longer lager than Max buff len"); 81 return; 82 } 83 byte[] mBuff = System.BitConverter.GetBytes(data); 84 Pack(mBuff, curDatalen); 85 } 86 public void Pack32bit(float data) 87 { 88 ushort curDatalen = 4; 89 if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff) 90 { 91 MonoBehaviour.print("Pack32bit(float) longer lager than Max buff len"); 92 return; 93 } 94 byte[] mBuff = System.BitConverter.GetBytes(data); 95 Pack(mBuff, curDatalen); 96 } 97 public void Pack64bit(double data) 98 { 99 ushort curDatalen = 8; 100 if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff) 101 { 102 MonoBehaviour.print("Pack64bit(double) longer lager than Max buff len"); 103 return; 104 } 105 byte[] mBuff = System.BitConverter.GetBytes(data); 106 Pack(mBuff, curDatalen); 107 } 108 public void Pack64bit(long data) 109 { 110 ushort curDatalen = 8; 111 if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff) 112 { 113 MonoBehaviour.print("Pack64bit(long) longer lager than Max buff len"); 114 return; 115 } 116 byte[] mBuff = System.BitConverter.GetBytes(data); 117 Pack(mBuff, curDatalen); 118 } 119 120 public void PackString(string data, ushort len) 121 { 122 ushort curDatalen = len; 123 if (m_OnePackIndex + curDatalen > m_MaxOnePackBuff) 124 { 125 MonoBehaviour.print("PackString() longer lager than Max buff len"); 126 return; 127 } 128 byte[] mBuff = System.Text.Encoding.UTF8.GetBytes(data); 129 Pack(mBuff, curDatalen); 130 } 131 132 void Pack(byte[] data, ushort len) 133 { 134 System.Buffer.BlockCopy(data, 0, m_OnePack, m_OnePackIndex, len); 135 m_OnePackIndex += len; 136 } 137 138 public byte[] GetByte() 139 { 140 return m_OnePack; 141 } 142 143 public int GetByteLen() 144 { 145 return m_OnePackIndex; 146 } 147 } 148 }
MsgUnPack.cs 解包类,返回类型不够自己扩展
1 using UnityEngine; 2 /* 3 * 通信协议 4 * 消息头前2字节保存当前消息长度 5 * 后面跟4字节表示消息ID 6 * 再后面是消息实质内容 7 */ 8 9 namespace LanSocket 10 { 11 class MsgUnPack : PackBase 12 { 13 ushort m_PackLen; 14 int m_MsgID; 15 public MsgUnPack() 16 { 17 } 18 19 void GetHead() 20 { 21 m_PackLen = System.BitConverter.ToUInt16(m_OnePack, 0); 22 m_MsgID = System.BitConverter.ToUInt16(m_OnePack, 2); 23 m_OnePackIndex = 6; 24 } 25 26 public MsgUnPack(byte[] mBuff, ushort len) 27 { 28 UnPack(mBuff, len); 29 } 30 31 public MsgUnPack(byte[] mBuff, ushort offset, ushort len) 32 { 33 UnPack(mBuff, offset, len); 34 } 35 36 public void UnPack(byte[] mBuff, ushort len) 37 { 38 System.Buffer.BlockCopy(mBuff, 0, m_OnePack, 0, len); 39 GetHead(); 40 } 41 42 public void UnPack(byte[] mBuff, ushort offset, ushort len) 43 { 44 System.Buffer.BlockCopy(mBuff, offset, m_OnePack, 0, len); 45 GetHead(); 46 } 47 48 public bool Readbool() 49 { 启灵网络(广州)|聘后端开发/U3D手游客户端/ 游戏测试/次世代场景模型等