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