c# socket select 模型代码(u3d)

Posted 武装三藏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c# socket select 模型代码(u3d)相关的知识,希望对你有一定的参考价值。

其实写过多次网络链接。但是因为换了工作,又没电脑在身边,所以以前的代码都没办法翻出来用。

所以从今天起,一些常用的代码只好放到网上。

公司有一个局域网的游戏。本来想用u3d的rpc就可以完成。但是后来说要传语音。于是只有写一个tcp。

目前完成的模块大的说就两块,网络和消息分发。

服务器有玩家池的管理。

网络部分没有想得很详细。因为是局域网,所以也不存在多大开销。如果有需要上千的需求,可能还要优化下代码结构以及锁。

有缘之人自取。

无论你干什么,我都没任何要求。唯一的要求,如果你发现有bug,或者什么地方改改更好,请告诉我。谢谢!

socket部分

  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         static Queue<int> m_MsgOrder;
 52 
 53         static Socket m_ServerSocket;
 54         static Thread m_LinstenThread;
 55         static Thread m_ReciveThread;
 56         static System.Collections.ArrayList m_ServerSocketList;
 57         static System.Collections.ArrayList m_listenSocketList;
 58         static System.Collections.ArrayList m_DeleteSocketList;
 59         static int m_MaxClientConnect = 10;
 60         static ClientConnect[] m_ConnectPool;
 61         static Queue<int> m_EmptyConnect;
 62         public static void Start()
 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             LanSocketBase.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, 8885));  //绑定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 static 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 static 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 static 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 static 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             LanSocketBase.BaseRelease();
364         }
365 
366         /// <summary>  
367         /// 销毁一个连接  
368         /// </summary>  
369         static 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("关闭一个连接,编号:" +如何中断 Socket.Select

U3D如何做代码混淆

Socket I/O模型之select模型

C#代码,运用button控制键盘。

socket编程:多路复用之select模型

socket select()模型