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

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

你问为什么会利己?

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

时间: 2024-10-21 21:25:20

u3d局域网游戏网络(c# socket select 模型)的相关文章

u3d局域网游戏网络(c# socket select 模型)——续

原文:http://www.cnblogs.com/saucerman/p/5555793.html 因为项目要加语音.语音数据都非常大.所以顺带就把之前写的网络模块一起测试了. 然后发现了一些bug,逐修.本来想在原文上面直接修改掉.但是恐怕已经看到的人拿去用了之后,再回头看也不一定能看明白,索性再写一文,将新文件直接放上来. 错误修改: 网络接收数据后,有一种情况没有处理完整,导致接收数据之后数据池的计数器没有向后偏移 网络数据处理后,当当前包仅剩1字节,下一个次数据进来的时候,需要2字节才

c# socket select 模型代码(u3d)

其实写过多次网络链接.但是因为换了工作,又没电脑在身边,所以以前的代码都没办法翻出来用. 所以从今天起,一些常用的代码只好放到网上. 公司有一个局域网的游戏.本来想用u3d的rpc就可以完成.但是后来说要传语音.于是只要写一个tcp. 先给出服务器和客户端的socket代码段.其他依赖的一些文件,就不贴了. 目前完成的模块大的说就两块,网络和消息分发. 网络部分服务器有玩家池的管理. 网络部分没有想得很详细.因为是局域网,所以也不存在多大开销.如果有需要上千的需求,可能还要优化下代码结构以及锁.

socket select模型

由于socket recv()方法是堵塞式的,当多个客户端连接服务器时,其中一个socket的recv调用时,会产生堵塞,使其他连接不能继续. 如果想改变这种一直等下去的焦急状态,可以多线程来实现(不再等待,同时去recv,同时阻塞),每个socket连接使用一个线程,这样效率十分低下,根本不可能应对负荷较大的情况(是啊,占用各种资源,电脑啊,你耗不起). 这时候我们便可以采取select模型.select允许进程指示内核等待多个事件中的任何一个发生,并仅在有一个或多个事件发生或经历一段指定时间

socket select()模型

转载:http://www.cnblogs.com/xiangshancuizhu/archive/2012/10/05/2711882.html 由于socket recv()方法是阻塞式的,当有多个客户端连接服务器时,其中一个socket的recv调用产生了阻塞,使其他链接不能继续.如果想改变这种一直等下去的焦急状态,可以多线程来实现(不再等待,同时去recv,同时阻塞),每个socket连接使用一个线程,这样效率十分低下,根本不可能应对负荷较大的情况(是啊,占用各种资源,电脑啊,你耗不起)

【转载】socket select模型

由于socket recv()方法是堵塞式的,当多个客户端连接服务器时,其中一个socket的recv调用时,会产生堵塞,使其他连接不能继续. 如果想改变这种一直等下去的焦急状态,可以多线程来实现(不再等待,同时去recv,同时阻塞,呵呵),每个socket连接使用一个线程,这样效率十分低下,根本不可能应对负荷较大的情况(是啊,占用各种资源,电脑啊,你耗不起). 这时候我们便可以采取select模型. select允许进程指示内核等待多个事件中的任何一个发生,并仅在有一个或多个时间发生或经历一段

C# Socket select模型

http://www.cnblogs.com/Clingingboy/archive/2011/07/04/2097806.html http://www.cnblogs.com/RascallySnake/archive/2013/07/11/3185071.html http://www.cnblogs.com/ggzss/archive/2011/08/25/2153746.html http://blog.csdn.net/a497785609/article/details/12871

[00020]-[2015-09-18]-[00]-[Windows Socket Select 模型]

int select( int nfds; fd_set FAR* readfds; fd_set FAR* writefds; fd_set FAR* exceptfds; const struct timeval FAR* timeout; ); #define FD_SETSIZE 64typedef struct fd_set{ u_int fd_count; SOCKET fd_array[FD_SETSIZE];}fd_set; struct timeval{ long tv_sec

0729------Linux网络编程----------使用 select 、poll 和 epoll 模型 编写客户端程序

1.select 模型 1.1 select 函数原型如下,其中 nfds 表示的描述符的最大值加1(因为这里是左闭右开区间),中间三个参数分别表示要监听的不同类型描述符的集合,timeout用来表示轮询的时间间隔,这里用NULL表示无限等待. 1.2 使用 select函数编写客户端程序的一般步骤: a)初始化参数,包括初始化监听集合read_set并添加fd,以及初始化监听的最大描述符 maxfd 和select的返回值 nready: b)将read_set 赋值给 ready_set,因

windows socket编程select模型使用

int select( int nfds,            //忽略 fd_ser* readfds,    //指向一个套接字集合,用来检测其可读性 fd_set* writefds,   // 指向一个套接字结合,用来检测其可写性 fd_ser* exceptfds, //指向一个套接字集合,用来检测错误 const struct timeval * timeout   //指定此函数等待的最长时间,如果为NULL,则最长时间为无限大. ); 参数说明: (1)   nfds  win