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 }
ClientMsgUnPack.cs

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 }
EventDispath.cs

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 }
LanSocketBase.cs

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 }
MsgPack.cs

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         {
 50             if (m_OnePackIndex + 1 > m_PackLen)
 51             {
 52                 MonoBehaviour.print("Readbool() longer lager than Max buff len");
 53                 return false;
 54             }
 55             bool data = System.BitConverter.ToBoolean(m_OnePack, m_OnePackIndex);
 56             ++m_OnePackIndex;
 57             return data;
 58         }
 59 
 60         public short ReadShort()
 61         {
 62             if (m_OnePackIndex + 2 > m_PackLen)
 63             {
 64                 MonoBehaviour.print("ReadShort() longer lager than Max buff len");
 65                 return 0;
 66             }
 67             short data = System.BitConverter.ToInt16(m_OnePack, m_OnePackIndex);
 68             m_OnePackIndex += 2;
 69             return data;
 70         }
 71 
 72         public ushort ReadUShort()
 73         {
 74             if (m_OnePackIndex + 2 > m_PackLen)
 75             {
 76                 MonoBehaviour.print("ReadUShortbit() longer lager than Max buff len");
 77                 return 0;
 78             }
 79             ushort data = System.BitConverter.ToUInt16(m_OnePack, m_OnePackIndex);
 80             m_OnePackIndex += 2;
 81             return data;
 82         }
 83 
 84         public int ReadInt()
 85         {
 86             if (m_OnePackIndex + 4 > m_PackLen)
 87             {
 88                 MonoBehaviour.print("ReadInt() longer lager than Max buff len");
 89                 return 0;
 90             }
 91             int data = System.BitConverter.ToInt32(m_OnePack, m_OnePackIndex);
 92             m_OnePackIndex += 4;
 93             return data;
 94         }
 95 
 96         public uint ReadUInt()
 97         {
 98             if (m_OnePackIndex + 4 > m_PackLen)
 99             {
100                 MonoBehaviour.print("ReadUInt() longer lager than Max buff len");
101                 return 0;
102             }
103             uint data = System.BitConverter.ToUInt32(m_OnePack, m_OnePackIndex);
104             m_OnePackIndex += 4;
105             return data;
106         }
107 
108         public float ReadFloat()
109         {
110             if (m_OnePackIndex + 4 > m_PackLen)
111             {
112                 MonoBehaviour.print("ReadFloat() longer lager than Max buff len");
113                 return 0.0f;
114             }
115             float data = System.BitConverter.ToSingle(m_OnePack, m_OnePackIndex);
116             m_OnePackIndex += 4;
117             return data;
118         }
119 
120         public double ReadDouble()
121         {
122             if (m_OnePackIndex + 8 > m_PackLen)
123             {
124                 MonoBehaviour.print("ReadDouble() longer lager than Max buff len");
125                 return 0.0f;
126             }
127             double data = System.BitConverter.ToDouble(m_OnePack, m_OnePackIndex);
128             m_OnePackIndex += 8;
129             return data;
130         }
131 
132         public long ReadLong()
133         {
134             if (m_OnePackIndex + 8 > m_PackLen)
135             {
136                 MonoBehaviour.print("ReadLong() longer lager than Max buff len");
137                 return 0;
138             }
139             long data = System.BitConverter.ToInt64(m_OnePack, m_OnePackIndex);
140             m_OnePackIndex += 8;
141             return data;
142         }
143 
144         public ulong ReadULong()
145         {
146             if (m_OnePackIndex + 8 > m_PackLen)
147             {
148                 MonoBehaviour.print("ReadULong() longer lager than Max buff len");
149                 return 0;
150             }
151             ulong data = System.BitConverter.ToUInt64(m_OnePack, m_OnePackIndex);
152             m_OnePackIndex += 8;
153             return data;
154         }
155 
156         public string ReadString(ushort len)
157         {
158             if (m_OnePackIndex + len > m_PackLen)
159             {
160                 MonoBehaviour.print("ReadString() longer lager than Max buff len");
161                 return "";
162             }
163             string data = System.Text.Encoding.UTF8.GetString(m_OnePack, m_OnePackIndex, len);
164             m_OnePackIndex += len;
165             return data;
166         }
167 
168         public int GetMsgID()
169         {
170             return m_MsgID;
171         }
172     }
173 }
MsgUnPack.cs

PackBase.cs 没什么实际意义,主要就是打包和解包类都会使用到的一些数据

 1 using System.Threading;
 2 
 3 /*
 4  *轻量级局域网服务器。 
 5  * 协议如下
 6  * 消息头前2字节保存当前消息长度
 7  * 后面跟4字节表示消息ID
 8  * 再后面是消息实质内容
 9  */
10 
11 namespace LanSocket
12 {
13     public class PackBase
14     {
15         protected int m_MaxOnePackBuff;
16         protected byte[] m_OnePack;
17         protected int m_OnePackIndex;
18 
19         public PackBase()
20         {
21             m_MaxOnePackBuff = LanSocketBase.m_MaxOnePackBuff;
22             m_OnePack = new byte[m_MaxOnePackBuff];
23             m_OnePackIndex = 0;
24         }
25     }
26 }
PackBase.cs

SocketBase.cs 同上

 1 using System.Net.Sockets;
 2 using System.Threading;
 3 using System.Net;
 4 
 5 public class SocketBase
 6 {
 7     protected bool m_HasInit = false;
 8     protected Socket m_Socket;
 9     protected Thread m_LinstenThread;
10     protected IPEndPoint m_IP;
11     protected Mutex m_Mutex;
12 }
SocketBase.cs

新增的广播类(broadcast)

特别说下,udp没有握手,所以socket对象在shutdown的时候会出异常,具体知识我也不知道,我是试出来的,有知道的还望不吝赐教。

ReciveBroadcast.cs 广播接收器。服务器段需要长期保持打开,因为只要有新用户加入,服务器就需要下发数据。而客户端不需要,因为客户端一但连上,就不需要广播系统了。所以服务器长期保留,客户端用完销毁

 1 using UnityEngine;
 2 using System.Net.Sockets;
 3 using System.Net;
 4 using System.Threading;
 5 using System.Collections.Generic;
 6 
 7 class ReciveBroadcast : SocketBase
 8 {
 9     public Queue<string> m_ServerIP;
10     public void Start(int port)
11     {
12         if (m_HasInit)
13         {
14             return;
15         }
16         try
17         {
18             m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
19             m_IP = new IPEndPoint(IPAddress.Any, port);
20             m_Socket.Bind(m_IP);
21             MonoBehaviour.print("广播网络启动监听" + m_Socket.LocalEndPoint.ToString());
22             m_LinstenThread = new Thread(ListenClientConnect);
23             m_LinstenThread.Start();
24             m_ServerIP = new Queue<string>();
25             m_Mutex = new Mutex();
26             m_HasInit = true;
27         }
28         catch (System.Exception ex)
29         {
30             MonoBehaviour.print("Broadcast reciver Start catch:" + ex.Message);
31         }
32     }
33 
34     void ListenClientConnect()
35     {
36         EndPoint ep = (EndPoint)m_IP;
37         try
38         {
39             while (true)
40             {
41                 Thread.Sleep(1);
42                 byte[] data = new byte[64];
43                 int recv = m_Socket.ReceiveFrom(data, ref ep);
44                 string stringData = System.Text.Encoding.UTF8.GetString(data, 0, recv);
45                 m_Mutex.WaitOne();
46                 m_ServerIP.Enqueue(stringData);
47                 m_Mutex.ReleaseMutex();
48                 MonoBehaviour.print("received: " + stringData + " from: " + ep.ToString());
49             }
50         }
51         catch (System.Exception ex)
52         {
53             MonoBehaviour.print("Broadcast reciver ListenClientConnect out:" + ex.Message);
54         }
55     }
56 
57     public void Destroy()
58     {
59         if (!m_HasInit)
60         {
61             return;
62         }
63         m_Socket.Close();
64         m_LinstenThread.Abort();
65     }
66 
67     public string GetIP()
68     {
69         if (!m_HasInit)
70         {
71             return "";
72         }
73 
74         try
75         {
76             m_Mutex.WaitOne();
77             if (0 != m_ServerIP.Count)
78             {
79                 m_Mutex.ReleaseMutex();
80                 return m_ServerIP.Dequeue();
81             }
82             m_Mutex.ReleaseMutex();
83         }
84         catch (System.Exception ex)
85         {
86             MonoBehaviour.print("Broadcast GetIP catch:" + ex.Message);
87             return "";
88         }
89         return "";
90     }
91 }
ReciveBroadcast.cs

SendBroadcast.cs 广播发射器。同上

 1 using UnityEngine;
 2 using System.Net.Sockets;
 3 using System.Net;
 4 
 5 class SendBroadcast : SocketBase
 6 {
 7     byte[] m_MyIP;
 8     public void Start(int port)
 9     {
10         if (m_HasInit)
11         {
12             return;
13         }
14         try
15         {
16             m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
17             m_IP = new IPEndPoint(IPAddress.Broadcast, port);//255.255.255.255
18             //m_IP = new IPEndPoint(IPAddress.Parse("192.168.255.255"), 9050);
19 
20             string mLocalIP = "";
21             string hostname = Dns.GetHostName();
22             IPHostEntry localHost = Dns.GetHostEntry(hostname);
23             for (int i = 0; i < localHost.AddressList.Length; ++i)
24             {
25                 if (localHost.AddressList[i].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
26                 {
27                     //MonoBehaviour.print(localHost.AddressList[i].ToString());
28                     mLocalIP = localHost.AddressList[i].ToString();
29                     break;
30                 }
31             }
32 
33             if ("".Equals(m_MyIP))
34             {
35                 MonoBehaviour.print("网络检测异常。请检查网络设置或接入网络");
36                 m_Socket.Close();
37                 m_Socket = null;
38                 return;
39             }
40             m_MyIP = System.Text.Encoding.UTF8.GetBytes(mLocalIP);
41             m_Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
42             m_HasInit = true;
43         }
44         catch (System.Exception ex)
45         {
46             MonoBehaviour.print("Broadcast sender Start catch:" + ex.Message);
47         }
48     }
49 
50     public void Send()
51     {
52         if(null != m_Socket)
53         {
54             MonoBehaviour.print("send a broadcast");
55             m_Socket.SendTo(m_MyIP, m_IP);
56         }
57     }
58 
59     public void Destroy()
60     {
61         if (!m_HasInit)
62         {
63             return;
64         }
65         m_Socket.Close();
66     }
67 }
SendBroadcast.cs

说明:网络模块也是根据网络上的代码加以修正和自己的经验修改完成。对于c# socket函数不熟,如果有什么地方可以优化或者用错或者传错参数,请指出赐教。

客户端网络(client)

SocketClient.cs 客户端网络模块。包含连接服务器、接受范围、处理返回数据等。

  1 using System.Net.Sockets;
  2 using System.Net;
  3 using System.Threading;
  4 using UnityEngine;
  5 using System.Collections.Generic;
  6 
  7 /*
  8  *轻量级局域网服务器。 
  9  * 协议如下
 10  * 消息头前2字节保存当前消息长度
 11  * 后面跟4字节表示消息ID
 12  * 再后面是消息实质内容
 13  */
 14 
 15 namespace LanSocket
 16 {
 17     class Client : LanSocketBase
 18     {
 19         Thread m_ReciveThread;
 20         Socket m_Connect;
 21         byte[] m_AllData;
 22         int m_AllDataHead;
 23         int m_AllDataEnd;
 24         int m_MsgNum;
 25 
 26         public void Start(string strIP, int port)
 27         {
 28             if (m_HasInit)
 29             {
 30                 return;
 31             }
 32             //设定服务器IP地址  
 33             IPAddress ip = IPAddress.Parse(strIP);
 34             Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 35             try
 36             {
 37                 temp.Connect(new IPEndPoint(ip, port)); //配置服务器IP与端口  
 38                 MonoBehaviour.print("连接服务器成功");
 39 
 40                 BaseInit();
 41                 m_Connect = temp;
 42                 m_ReciveThread = new Thread(ReceiveMessage);
 43                 m_ReciveThread.Start();
 44                 m_AllData = new byte[LanSocketBase.m_MaxAllBuff + 1];
 45                 m_AllDataHead = 0;
 46                 m_AllDataEnd = 0;
 47                 m_MsgNum = 0;
 48             }
 49             catch (System.Exception ex)
 50             {
 51                 MonoBehaviour.print("连接服务器失败: " + ex.Message);
 52                 return;
 53             }
 54         }
 55 
 56         private void PutDataToBuff(byte[] mClientSendBuff, int mReceiveNumber)
 57         {
 58             if (m_AllDataEnd + mReceiveNumber >= LanSocketBase.m_MaxAllBuff)
 59             {
 60                 byte[] mCurAllData = new byte[m_AllDataEnd - m_AllDataHead];
 61                 System.Buffer.BlockCopy(m_AllData, m_AllDataHead, mCurAllData, 0, m_AllDataEnd - m_AllDataHead);
 62                 System.Buffer.BlockCopy(mCurAllData, 0, m_AllData, 0, m_AllDataEnd - m_AllDataHead);
 63                 m_AllDataEnd -= m_AllDataHead;
 64                 m_AllDataHead = 0;
 65             }
 66             int mOnePackStartPos = 0;
 67             while (mReceiveNumber > 0)
 68             {
 69                 if (0 == m_OnePackIndex)
 70                 {
 71                     ushort datalen = System.BitConverter.ToUInt16(mClientSendBuff, mOnePackStartPos);
 72                     if (datalen <= mReceiveNumber)
 73                     {
 74                         System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_AllData, m_AllDataEnd, datalen);
 75                         m_AllDataEnd += datalen;
 76 
 77                         mOnePackStartPos += datalen;
 78 
 79                         mReceiveNumber -= datalen;
 80                         ++m_MsgNum;
 81                     }
 82                     else
 83                     {
 84                         System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mReceiveNumber);
 85                         m_OnePackIndex += mReceiveNumber;
 86                         mOnePackStartPos += mReceiveNumber;
 87 
 88                         mReceiveNumber -= mReceiveNumber;
 89                     }
 90                 }
 91                 else
 92                 {
 93                     ushort datalen = System.BitConverter.ToUInt16(m_OnePack, 0);
 94                     if (m_OnePackIndex + mReceiveNumber >= datalen)
 95                     {
 96                         int mNeedNum = datalen - m_OnePackIndex;
 97                         System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mNeedNum);
 98                         mOnePackStartPos += mNeedNum;
 99                         
100                         System.Buffer.BlockCopy(m_OnePack, 0, m_AllData, m_AllDataEnd, datalen);
101                         m_OnePackIndex = 0;
102 
103                         mReceiveNumber -= mNeedNum;
104                     }
105                     else
106                     {
107                         System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mReceiveNumber);
108                         m_OnePackIndex += mReceiveNumber;
109                         mOnePackStartPos += mReceiveNumber;
110 
111                         mReceiveNumber -= mReceiveNumber;
112                     }
113                 }
114             }
115         }
116 
117         public void Destroy()
118         {
119             if (!m_HasInit)
120             {
121                 return;
122             }
123             BaseRelease();
124             ShutDownConnect();
125             m_MsgNum = 0;
126         }
127 
128         public void GetMsg(ref MsgUnPack msg)
129         {
130             if (!m_HasInit)
131             {
132                 return;
133             }
134             try
135             {
136                 Lock();
137                 if (0 != m_MsgNum)
138                 {
139                     ushort datalen = System.BitConverter.ToUInt16(m_AllData, m_AllDataHead);
140                     msg = new MsgUnPack(m_AllData, (ushort)m_AllDataHead, (ushort)datalen);
141                     m_AllDataHead += datalen;
142                     --m_MsgNum;
143                 }
144             }
145             finally
146             {
147                 UnLock();
148             }
149         }
150 
151         /// <summary>  
152         /// 接收消息  
153         /// </summary>  
154         public void ReceiveMessage()
155         {
156             while (true)
157             {
158                 Thread.Sleep(1);
159                 try
160                 {
161                     //通过clientSocket接收数据  
162                     byte[] mClientSendBuff = new byte[m_MaxOnePackBuff + 1];
163                     int mReceiveNumber = m_Connect.Receive(mClientSendBuff);
164                     if (0 == mReceiveNumber)
165                     {
166                         MonoBehaviour.print("disconnect");
167                         ShutDownConnect();
168                     }
169                     else if (mReceiveNumber > 0)
170                     {
171                         try
172                         {
173                             Lock();
174                             PutDataToBuff(mClientSendBuff, mReceiveNumber);
175                         }
176                         catch (System.Exception ex)
177                         {
178                             MonoBehaviour.print("PutDataToBuff catch: " + ex.Message);
179                         }
180                         finally
181                         {
182                             UnLock();
183                         }
184                     }
185                     else
186                     {
187                         MonoBehaviour.print("one connect recive a error num: " + mReceiveNumber.ToString());
188                     }
189                 }
190                 catch (System.Exception ex)
191                 {
192                     MonoBehaviour.print("ReceiveMessage catch: " + ex.Message);
193                     ShutDownConnect();
194                 }
195             }
196         }
197 
198         public void Send(ref MsgPack msg)
199         {
200             try
201             {
202                 Lock();
203                 m_Connect.Send(msg.GetByte(), msg.GetByteLen(), SocketFlags.None);
204             }
205             finally
206             {
207                 UnLock();
208             }
209         }
210 
211         public void ShutDownConnect()
212         {
213             m_ReciveThread.Abort();
214             if (m_Connect.Connected)
215             {
216                 m_Connect.Shutdown(SocketShutdown.Both);
217             }
218             m_Connect.Close();
219         }
220     }
221 }
SocketClient.cs

服务器网络(server)

SocketServer.cs 服务器网络模块。同上,额外有玩家池。

  1 using System.Net.Sockets;
  2 using System.Net;
  3 using System.Threading;
  4 using UnityEngine;
  5 using System.Collections.Generic;
  6 /*
  7  *轻量级局域网服务器。 
  8  * 协议如下
  9  * 消息头前2字节保存当前消息长度
 10  * 后面跟4字节表示消息ID
 11  * 再后面是消息实质内容
 12  */
 13 
 14 namespace LanSocket
 15 {
 16     class ClientConnect
 17     {
 18         public byte[] m_AllData;
 19         public int m_AllDataHead;
 20         public int m_AllDataEnd;
 21         public int m_MsgCount;
 22         public byte[] m_OnePack;
 23         public int m_OnePackIndex;
 24         public Socket m_Connect;
 25         public long m_UserID;
 26 
 27         public ClientConnect()
 28         {
 29             m_AllData = new byte[LanSocketBase.m_MaxAllBuff];
 30             m_AllDataHead = 0;
 31             m_AllDataEnd = 0;
 32             m_MsgCount = 0;
 33             m_OnePack = new byte[LanSocketBase.m_MaxOnePackBuff];
 34             m_OnePackIndex = 0;
 35             m_Connect = null;
 36             m_UserID = 0;
 37         }
 38 
 39         public void Reset()
 40         {
 41             m_AllDataHead = 0;
 42             m_AllDataEnd = 0;
 43             m_MsgCount = 0;
 44             m_OnePackIndex = 0;
 45             m_Connect = null;
 46             m_UserID = 0;
 47         }
 48     }
 49     class Server : LanSocketBase
 50     {
 51         Queue<int> m_MsgOrder;
 52 
 53         Socket m_ServerSocket;
 54         Thread m_LinstenThread;
 55         Thread m_ReciveThread;
 56         System.Collections.ArrayList m_ServerSocketList;
 57         System.Collections.ArrayList m_listenSocketList;
 58         System.Collections.ArrayList m_DeleteSocketList;
 59         int m_MaxClientConnect = 10;
 60         ClientConnect[] m_ConnectPool;
 61         Queue<int> m_EmptyConnect;
 62         public void Start(int port)
 63         {
 64             if (m_HasInit)
 65             {
 66                 return;
 67             }
 68             string mLocalIP = "";
 69 
 70             string mHostName = Dns.GetHostName();
 71             IPHostEntry localHost = Dns.GetHostEntry(mHostName);
 72             for (int i = 0; i < localHost.AddressList.Length; ++i)
 73             {
 74                 if (localHost.AddressList[i].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
 75                 {
 76                     //MonoBehaviour.print(localHost.AddressList[i].ToString());
 77                     mLocalIP = localHost.AddressList[i].ToString();
 78                     break;
 79                 }
 80             }
 81 
 82             if ("".Equals(mLocalIP))
 83             {
 84                 MonoBehaviour.print("网络检测异常。请检查网络设置或接入网络");
 85                 return;
 86             }
 87             BaseInit();
 88             m_MsgOrder = new Queue<int>();
 89 
 90             //服务器IP地址  
 91             IPAddress ip = IPAddress.Parse(mLocalIP);
 92             m_ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 93             m_ServerSocket.Bind(new IPEndPoint(ip, port));  //绑定IP地址:端口  
 94             m_ServerSocket.Listen(10);    //设定最多10个排队连接请求  
 95             MonoBehaviour.print("游戏网络启动监听" + m_ServerSocket.LocalEndPoint.ToString());
 96 
 97             m_ServerSocketList = new System.Collections.ArrayList();
 98             m_listenSocketList = new System.Collections.ArrayList();
 99             m_DeleteSocketList = new System.Collections.ArrayList();
100 
101             m_ConnectPool = new ClientConnect[m_MaxClientConnect];
102             m_EmptyConnect = new Queue<int>();
103             for (int i = 0; i < m_MaxClientConnect; ++i)
104             {
105                 m_ConnectPool[i] = new ClientConnect();
106                 m_EmptyConnect.Enqueue(i);
107             }
108             //通过Clientsoket发送数据  
109             m_ReciveThread = new Thread(ReceiveMessage);
110             m_ReciveThread.Start();
111             m_LinstenThread = new Thread(ListenClientConnect);
112             m_LinstenThread.Start();
113         }
114 
115         /// <summary>  
116         /// 监听客户端连接  
117         /// </summary>  
118         public void ListenClientConnect()
119         {
120             while (true)
121             {
122                 Thread.Sleep(500);
123                 m_ServerSocketList.Add(m_ServerSocket);
124                 Socket.Select(m_ServerSocketList, null, null, 1000);
125                 for (int i = 0; i < m_ServerSocketList.Count; ++i)
126                 {
127                     Socket clientSocket = ((Socket)m_ServerSocketList[i]).Accept();
128                     if (null != clientSocket)
129                     {
130                         try
131                         {
132                             Lock();
133                             if (0 == m_EmptyConnect.Count)
134                             {
135                                 MonoBehaviour.print("链接已经达到最大上线,丢弃当前连接");
136                                 clientSocket.Shutdown(SocketShutdown.Both);
137                                 clientSocket.Close();
138                             }
139                             else
140                             {
141                                 //m_listenSocketList.Add(clientSocket);
142                                 int mSlot = m_EmptyConnect.Dequeue();
143                                 m_ConnectPool[mSlot].m_Connect = clientSocket;
144                                 m_ConnectPool[mSlot].m_UserID = System.DateTime.Now.ToFileTime();
145                                 MonoBehaviour.print("成功连接一个客户端,编号:" + mSlot.ToString());
146                             }
147                         }
148                         finally
149                         {
150                             UnLock();
151                         }
152                     }
153                 }
154                 m_ServerSocketList.Clear();
155             }
156         }
157 
158         private bool PutDataToBuff(byte[] mClientSendBuff, int mReceiveNumber, Socket client)
159         {
160             ClientConnect curPlayer = null;
161             int mSlot = -1;
162             for (int i = 0; i < m_MaxClientConnect; ++i)
163             {
164                 if (client == m_ConnectPool[i].m_Connect)
165                 {
166                     curPlayer = m_ConnectPool[i];
167                     mSlot = i;
168                     break;
169                 }
170             }
171             if (null == curPlayer)
172             {
173                 return false;
174             }
175             if (curPlayer.m_AllDataEnd + mReceiveNumber >= LanSocketBase.m_MaxAllBuff)
176             {
177                 byte[] mCurAllData = new byte[curPlayer.m_AllDataEnd - curPlayer.m_AllDataHead];
178                 System.Buffer.BlockCopy(curPlayer.m_AllData, curPlayer.m_AllDataHead, mCurAllData, 0, curPlayer.m_AllDataEnd - curPlayer.m_AllDataHead);
179                 System.Buffer.BlockCopy(mCurAllData, 0, curPlayer.m_AllData, 0, curPlayer.m_AllDataEnd - curPlayer.m_AllDataHead);
180                 curPlayer.m_AllDataEnd -= curPlayer.m_AllDataHead;
181                 curPlayer.m_AllDataHead = 0;
182             }
183             int mOnePackStartPos = 0;
184             while (mReceiveNumber > 0)
185             {
186                 if (0 == m_OnePackIndex)
187                 {
188                     ushort datalen = System.BitConverter.ToUInt16(mClientSendBuff, mOnePackStartPos);
189                     if (datalen > LanSocketBase.m_MaxOnePackBuff || datalen < LanSocketBase.m_HeadSize)
190                     {
191                         return false;
192                     }
193                     if (datalen <= mReceiveNumber)
194                     {
195                         System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, curPlayer.m_AllData, curPlayer.m_AllDataEnd, datalen);
196                         curPlayer.m_AllDataEnd += datalen;
197                         mOnePackStartPos += datalen;
198 
199                         mReceiveNumber -= datalen;
200 
201                         m_MsgOrder.Enqueue(mSlot);
202                     }
203                     else
204                     {
205                         System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mReceiveNumber);
206                         m_OnePackIndex += mReceiveNumber;
207                         mOnePackStartPos += mReceiveNumber;
208 
209                         mReceiveNumber -= mReceiveNumber;
210                     }
211                 }
212                 else
213                 {
214                     ushort datalen = System.BitConverter.ToUInt16(m_OnePack, 0);
215                     if (datalen > LanSocketBase.m_MaxOnePackBuff || datalen < LanSocketBase.m_HeadSize)
216                     {
217                         return false;
218                     }
219                     if (m_OnePackIndex + mReceiveNumber >= datalen)
220                     {
221                         int mNeedNum = datalen - m_OnePackIndex;
222                         System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mNeedNum);
223                         mOnePackStartPos += mNeedNum;
224 
225                         System.Buffer.BlockCopy(m_OnePack, 0, curPlayer.m_AllData, curPlayer.m_AllDataEnd, datalen);
226                         m_OnePackIndex = 0;
227 
228                         mReceiveNumber -= mNeedNum;
229 
230                         m_MsgOrder.Enqueue(mSlot);
231                     }
232                     else
233                     {
234                         System.Buffer.BlockCopy(mClientSendBuff, mOnePackStartPos, m_OnePack, m_OnePackIndex, mReceiveNumber);
235                         m_OnePackIndex += mReceiveNumber;
236                         mOnePackStartPos += mReceiveNumber;
237 
238                         mReceiveNumber -= mReceiveNumber;
239                     }
240                 }
241             }
242 
243             return true;
244         }
245 
246         /// <summary>  
247         /// 接收消息  
248         /// </summary>  
249         public void ReceiveMessage()
250         {
251             try
252             {
253                 while (true)
254                 {
255                     Thread.Sleep(1);
256                     for (int i = 0; i < m_MaxClientConnect; ++i)
257                     {
258                         if (null != m_ConnectPool[i].m_Connect)
259                         {
260                             m_listenSocketList.Add(m_ConnectPool[i].m_Connect);
261                         }
262                     }
263                     if (0 == m_listenSocketList.Count)
264                     {
265                         continue;
266                     }
267                     Socket.Select(m_listenSocketList, null, null, 1000);
268                     for (int i = 0; i < m_listenSocketList.Count; ++i)
269                     {
270                         Socket mClient = (Socket)m_listenSocketList[i];
271                         //try
272                         //{
273                         //通过clientSocket接收数据  
274                         byte[] mClientSendBuff = new byte[m_MaxOnePackBuff];
275                         int mReceiveNumber = mClient.Receive(mClientSendBuff);
276                         if (0 == mReceiveNumber)
277                         {
278                             m_DeleteSocketList.Add(mClient);
279                         }
280                         else if (mReceiveNumber > 0)
281                         {
282                             try
283                             {
284                                 Lock();
285                                 bool rt = PutDataToBuff(mClientSendBuff, mReceiveNumber, mClient);
286                                 if (!rt)
287                                 {
288                                     m_DeleteSocketList.Add(mClient);
289                                 }
290                             }
291                             catch (System.Exception ex)
292                             {
293                                 MonoBehaviour.print("PutDataToBuff catch: " + ex.Message);
294                             }
295                             finally
296                             {
297                                 UnLock();
298                             }
299                         }
300                         else
301                         {
302                             MonoBehaviour.print("one connect recive a error num: " + mReceiveNumber.ToString());
303                         }
304                         //}
305                         //catch (System.Exception ex)
306                         //{
307                         //    MonoBehaviour.print("ReceiveMessage catch: " + ex.Message);
308                         //    m_DeleteSocketList.Add(mClient);
309                         //}
310                     }
311                     m_listenSocketList.Clear();
312                     if (0 != m_DeleteSocketList.Count)
313                     {
314                         ShutDownConnect();
315                     }
316                 }
317 
318             }
319             catch (System.Exception ex)
320             {
321                 MonoBehaviour.print("ReceiveMessage out:" + ex.Message);
322             }
323 
324         }
325 
326         /// <summary>  
327         /// 程序退出销毁  
328         /// </summary>  
329         public void Destroy()
330         {
331             if (!m_HasInit)
332             {
333                 return;
334             }
335             m_LinstenThread.Abort();
336             m_ReciveThread.Abort();
337             m_listenSocketList.Clear();
338 
339             for (int i = 0; i < m_ServerSocketList.Count; ++i)
340             {
341                 Socket mServer = (Socket)m_ServerSocketList[i];
342                 if (mServer.Connected)
343                 {
344                     mServer.Shutdown(SocketShutdown.Both);
345                 }
346                 mServer.Close();
347             }
348             m_ServerSocketList.Clear();
349 
350             for (int i = 0; i < m_MaxClientConnect; ++i)
351             {
352                 if (null != m_ConnectPool[i].m_Connect)
353                 {
354                     if (m_ConnectPool[i].m_Connect.Connected)
355                     {
356                         m_ConnectPool[i].m_Connect.Shutdown(SocketShutdown.Both);
357                     }
358                     m_ConnectPool[i].m_Connect.Close();
359                     m_ConnectPool[i].m_Connect = null;
360                 }
361             }
362             m_EmptyConnect.Clear();
363             BaseRelease();
364         }
365 
366         /// <summary>  
367         /// 销毁一个连接  
368         /// </summary>  
369         void ShutDownConnect()
370         {
371             try
372             {
373                 Lock();
374                 for (int j = 0; j < m_DeleteSocketList.Count; ++j)
375                 {
376                     Socket connect = (Socket)m_DeleteSocketList[j];
377                     for (int i = 0; i < m_MaxClientConnect; ++i)
378                     {
379                         if (connect == m_ConnectPool[i].m_Connect)
380                         {
381                             connect.Shutdown(SocketShutdown.Both);
382                             connect.Close();
383                             m_ConnectPool[i].Reset();
384                             m_EmptyConnect.Enqueue(i);
385                             MonoBehaviour.print("关闭一个连接,编号:" + i.ToString());
386                             break;
387                         }
388                     }
389                 }
390             }
391             catch (System.Exception ex)
392             {
393                 MonoBehaviour.print("ShutDownConnect catch: " + ex.Message);
394             }
395             finally
396             {
397                 m_DeleteSocketList.Clear();
398                 UnLock();
399             }
400         }
401 
402         /// <summary>  
403         /// 获取一个数据  
404         /// </summary>  
405         public void GetMsg(ref ClientMsgUnPack msg)
406         {
407             if(!m_HasInit)
408             {
409                 return;
410             }
411             try
412             {
413                 Lock();
414                 if (0 != m_MsgOrder.Count)
415                 {
416                     int mSlot = m_MsgOrder.Dequeue();
417                     ClientConnect curPlayer = m_ConnectPool[mSlot];
418                     ushort mOnePackLen = System.BitConverter.ToUInt16(curPlayer.m_AllData, curPlayer.m_AllDataHead);
419                     msg = new ClientMsgUnPack(curPlayer.m_AllData, (ushort)curPlayer.m_AllDataHead, (ushort)mOnePackLen, mSlot);
420                     msg.SetUserID(curPlayer.m_UserID);
421                     curPlayer.m_AllDataHead += mOnePackLen;
422                 }
423             }
424             finally
425             {
426                 UnLock();
427             }
428         }
429 
430         public void SendTo(ref MsgPack msg, long userID)
431         {
432             try
433             {
434                 Lock();
435                 for(int i = 0 ; i < m_MaxClientConnect ; ++i)
436                 {
437                     ClientConnect curPlayer = m_ConnectPool[i];
438                     if (null != curPlayer.m_Connect && curPlayer.m_UserID == userID)
439                     {
440                         curPlayer.m_Connect.Send(msg.GetByte(), msg.GetByteLen(), SocketFlags.None);
441                         break;
442                     }
443                 }
444             }
445             finally
446             {
447                 UnLock();
448             }
449         }
450 
451         public void SendToAll(ref MsgPack msg)
452         {
453             try
454             {
455                 Lock();
456                 for (int i = 0; i < m_MaxClientConnect; ++i)
457                 {
458                     ClientConnect curPlayer = m_ConnectPool[i];
459                     if (null != curPlayer.m_Connect)
460                     {
461                         curPlayer.m_Connect.Send(msg.GetByte(), msg.GetByteLen(), SocketFlags.None);
462                         break;
463                     }
464                 }
465             }
466             finally
467             {
468                 UnLock();
469             }
470         }
471     }
472 }
SocketServer.cs

外部配套模块

ClientMain.cs u3d下的一个启动客户端网络模块的控件

  1 using UnityEngine;
  2 using System.Collections;
  3 
  4 public class ClientMain : MonoBehaviour {
  5 
  6     // Use this for initialization
  7     ClientEventDispath m_Msg;
  8     SendBroadcast m_Sender;
  9     ReciveBroadcast m_Reciver;
 10     LanSocket.Client m_GameNet;
 11     string m_GameServerIP;
 12     bool m_bReady;
 13     float m_BroadTime;
 14 
 15     void Start () 
 16     {
 17         m_Sender = new SendBroadcast();
 18         m_Sender.Start(6666);
 19         m_Reciver = new ReciveBroadcast();
 20         m_Reciver.Start(6688);
 21 
 22         m_GameNet = new LanSocket.Client();
 23 
 24         m_GameServerIP = "";
 25 
 26         m_bReady = false;
 27         m_BroadTime = 0.0f;
 28 
 29         EventDispathBase.g_MaxEventNum = (int)NetMsgID.NET_MSG_END;
 30         m_Msg = new ClientEventDispath();
 31         m_Msg.RegistEvent((int)NetMsgID.S2C_SEND_ANIMAL_DATA, Action_S2C_SEND_ANIMAL_DATA);
 32     }
 33     
 34     // Update is called once per frame
 35     void Update ()
 36     {
 37         if (m_bReady)
 38         {
 39             LanSocket.MsgUnPack msg = null;
 40             m_GameNet.GetMsg(ref msg);
 41             if (null != msg)
 42             {
 43                 print("here have one msg on client");
 44             }
 45 
 46             if (Input.GetKeyUp(KeyCode.Space))
 47             {
 48                 LanSocket.MsgPack sendMsg = new LanSocket.MsgPack();
 49                 sendMsg.SetHead((int)NetMsgID.C2S_SELECT_ANIMAL);
 50                 sendMsg.Pack16bit(1);
 51                 sendMsg.PackEnd();
 52                 m_GameNet.Send(ref sendMsg);
 53                 print("send 1");
 54             }
 55         }
 56         else
 57         {
 58             m_GameServerIP = m_Reciver.GetIP();
 59             if ("".Equals(m_GameServerIP))
 60             {
 61                 m_BroadTime -= Time.deltaTime;
 62                 if(m_BroadTime - Time.deltaTime < 0.0f)
 63                 {
 64                     m_BroadTime = 5.0f;
 65                     m_Sender.Send();
 66                 }
 67             }
 68             else
 69             {
 70                 print("get broadcast ip:" + m_GameServerIP);
 71                 GameStart();
 72             }
 73         }
 74     }
 75     void OnDestroy()
 76     {
 77         m_GameNet.Destroy();
 78         if(null != m_Reciver)
 79         {
 80             m_Reciver.Destroy();
 81         }
 82         if (null != m_Sender)
 83         {
 84             m_Sender.Destroy();
 85         }
 86     }
 87 
 88     void GameStart()
 89     {
 90         m_bReady = true;
 91         m_GameNet.Start(m_GameServerIP, 8888);
 92         try
 93         {
 94             m_Reciver.Destroy();
 95             m_Sender.Destroy();
 96         }
 97         catch (System.Exception ex)
 98         {
 99             MonoBehaviour.print("GameStart catch:" + ex.Message);
100         }
101         m_Reciver = null;
102         m_Reciver = null;
103     }
104 
105     void Action_S2C_SEND_ANIMAL_DATA(LanSocket.MsgUnPack msg)
106     {
107     }
108 }
ClientMain.cs

Common.cs 定义的网络通信的消息ID

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 enum NetMsgID
 5 {
 6     NET_MSG_START = 100,
 7     S2C_SEND_ANIMAL_DATA,
 8     C2S_SELECT_ANIMAL,
 9 
10     NET_MSG_END,
11 }
Common.cs

ServerMain.cs u3d下的一个启动服务器网络模块的控件

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class ServerMain : MonoBehaviour 
 5 {
 6     bool m_Destroy;
 7     ServerEventDispath m_ClientMsg;
 8     ReciveBroadcast m_Reciver;
 9     SendBroadcast m_Sender;
10     LanSocket.Server m_GameNet;
11     void Start () 
12     {
13         m_Destroy = false;
14         //广播
15         m_Reciver = new ReciveBroadcast();
16         m_Reciver.Start(6666);
17         m_Sender = new SendBroadcast();
18         m_Sender.Start(6688);
19 
20         //游戏网络
21         m_GameNet = new LanSocket.Server();
22         m_GameNet.Start(8888);
23 
24         m_ClientMsg = new ServerEventDispath();
25         m_ClientMsg.RegistEvent(123, Action_123);
26     }
27     
28     // Update is called once per frame
29     void Update () 
30     {
31         if(!m_Destroy)
32         {
33             LanSocket.ClientMsgUnPack clientMsg = null;
34             m_GameNet.GetMsg(ref clientMsg);
35             if (null != clientMsg)
36             {
37                 print("Msg:" + clientMsg.GetMsgID() + " from: " + clientMsg.GetUserID());
38 
39                 EventNode mNode = new EventNode();
40                 mNode.m_EventID = clientMsg.GetMsgID(); ;
41                 mNode.msg = clientMsg;
42                 m_ClientMsg.AddEvent(mNode);
43             }
44 
45             if(!"".Equals(m_Reciver.GetIP()))
46             {
47                 m_Sender.Send();
48             }
49 
50             m_ClientMsg.Proccess();
51         }
52     }
53 
54     void OnDestroy()
55     {
56         m_Destroy = true;
57         m_GameNet.Destroy();
58         m_Reciver.Destroy();
59         m_Sender.Destroy();
60     }
61 
62     void Action_123(LanSocket.ClientMsgUnPack msg)
63     {
64         long userID = msg.GetUserID();
65         ushort accountLen = msg.ReadUShort();
66         string account = msg.ReadString(accountLen);
67         ushort passLen = msg.ReadUShort();
68         string pass = msg.ReadString(passLen);
69 
70         print("Action_123 account: " + account + " pass word: " + pass+" from user: " + userID);
71 
72         LanSocket.MsgPack sendMsg = new LanSocket.MsgPack();
73         sendMsg.SetHead(123);
74         string strAccount = "test account";
75         sendMsg.Pack16bit((ushort)strAccount.Length);
76         sendMsg.PackString(strAccount, (ushort)strAccount.Length);
77         string strPass = "test pass word";
78         sendMsg.Pack16bit((ushort)strPass.Length);
79         sendMsg.PackString(strPass, (ushort)strPass.Length);
80         sendMsg.PackEnd();
81         m_GameNet.SendTo(ref sendMsg, msg.GetUserID());
82     }
83 }
ServerMain.cs

伙计们,有代码分享出来。利人利己。

你问为什么会利己?

等你换了工作找不到原本的代码的时候你就知道传到网上是一件幸福的事。

原文地址:https://www.cnblogs.com/saucerman/p/5555793.html