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

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

公司有一个局域网的游戏。本来想用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 = ;
  31. m_AllDataEnd = ;
  32. m_MsgCount = ;
  33. m_OnePack = new byte[LanSocketBase.m_MaxOnePackBuff];
  34. m_OnePackIndex = ;
  35. m_Connect = null;
  36. m_UserID = ;
  37. }
  38.  
  39. public void Reset()
  40. {
  41. m_AllDataHead = ;
  42. m_AllDataEnd = ;
  43. m_MsgCount = ;
  44. m_OnePackIndex = ;
  45. m_Connect = null;
  46. m_UserID = ;
  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 = ;
  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 = ; 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, )); //绑定IP地址:端口
  94. m_ServerSocket.Listen(); //设定最多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 = ; 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();
  123. m_ServerSocketList.Add(m_ServerSocket);
  124. Socket.Select(m_ServerSocketList, null, null, );
  125. for (int i = ; 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 ( == 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 = -;
  162. for (int i = ; 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, , curPlayer.m_AllDataEnd - curPlayer.m_AllDataHead);
  179. System.Buffer.BlockCopy(mCurAllData, , curPlayer.m_AllData, , curPlayer.m_AllDataEnd - curPlayer.m_AllDataHead);
  180. curPlayer.m_AllDataEnd -= curPlayer.m_AllDataHead;
  181. curPlayer.m_AllDataHead = ;
  182. }
  183. int mOnePackStartPos = ;
  184. while (mReceiveNumber > )
  185. {
  186. if ( == 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, );
  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, , curPlayer.m_AllData, curPlayer.m_AllDataEnd, datalen);
  226. m_OnePackIndex = ;
  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();
  256. for (int i = ; 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 ( == m_listenSocketList.Count)
  264. {
  265. continue;
  266. }
  267. Socket.Select(m_listenSocketList, null, null, );
  268. for (int i = ; 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 ( == mReceiveNumber)
  277. {
  278. m_DeleteSocketList.Add(mClient);
  279. }
  280. else if (mReceiveNumber > )
  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 ( != 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 = ; 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 = ; 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 = ; j < m_DeleteSocketList.Count; ++j)
  375. {
  376. Socket connect = (Socket)m_DeleteSocketList[j];
  377. for (int i = ; 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 static void GetMsg(ref ClientMsgUnPack msg)
  406. {
  407. try
  408. {
  409. Lock();
  410. if ( != m_MsgOrder.Count)
  411. {
  412. int mSlot = m_MsgOrder.Dequeue();
  413. ClientConnect curPlayer = m_ConnectPool[mSlot];
  414. ushort mOnePackLen = System.BitConverter.ToUInt16(curPlayer.m_AllData, curPlayer.m_AllDataHead);
  415. msg = new ClientMsgUnPack(curPlayer.m_AllData, (ushort)curPlayer.m_AllDataHead, (ushort)mOnePackLen, mSlot);
  416. msg.SetUserID(curPlayer.m_UserID);
  417. curPlayer.m_AllDataHead += mOnePackLen;
  418. }
  419. }
  420. finally
  421. {
  422. UnLock();
  423. }
  424. }
  425.  
  426. public static void SendTo(ref MsgPack msg, long userID)
  427. {
  428. try
  429. {
  430. Lock();
  431. for(int i = ; i < m_MaxClientConnect ; ++i)
  432. {
  433. ClientConnect curPlayer = m_ConnectPool[i];
  434. if (null != curPlayer.m_Connect && curPlayer.m_UserID == userID)
  435. {
  436. curPlayer.m_Connect.Send(msg.GetByte(), msg.GetByteLen(), SocketFlags.None);
  437. break;
  438. }
  439. }
  440. }
  441. finally
  442. {
  443. UnLock();
  444. }
  445. }
  446.  
  447. public static void SendToAll(ref MsgPack msg)
  448. {
  449. try
  450. {
  451. Lock();
  452. for (int i = ; i < m_MaxClientConnect; ++i)
  453. {
  454. ClientConnect curPlayer = m_ConnectPool[i];
  455. if (null != curPlayer.m_Connect)
  456. {
  457. curPlayer.m_Connect.Send(msg.GetByte(), msg.GetByteLen(), SocketFlags.None);
  458. break;
  459. }
  460. }
  461. }
  462. finally
  463. {
  464. UnLock();
  465. }
  466. }
  467. }
  468. }

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. * 协议如下
  10. * 消息头前2字节保存当前消息长度
  11. * 后面跟4字节表示消息ID
  12. * 再后面是消息实质内容
  13. */
  14.  
  15. namespace LanSocket
  16. {
  17. class Client : LanSocketBase
  18. {
  19. static Thread m_ReciveThread;
  20. static Socket m_Connect;
  21. static byte[] m_AllData;
  22. static int m_AllDataHead;
  23. static int m_AllDataEnd;
  24. static int m_MsgNum;
  25.  
  26. public static void Start()
  27. {
  28. if (m_HasInit)
  29. {
  30. return;
  31. }
  32. //设定服务器IP地址
  33. IPAddress ip = IPAddress.Parse("192.168.1.109");
  34. Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  35. try
  36. {
  37. temp.Connect(new IPEndPoint(ip, )); //配置服务器IP与端口
  38. MonoBehaviour.print("连接服务器成功");
  39.  
  40. LanSocketBase.BaseInit();
  41. m_Connect = temp;
  42. m_ReciveThread = new Thread(ReceiveMessage);
  43. m_ReciveThread.Start();
  44. m_AllData = new byte[LanSocketBase.m_MaxAllBuff + ];
  45. m_AllDataHead = ;
  46. m_AllDataEnd = ;
  47. m_MsgNum = ;
  48. }
  49. catch
  50. {
  51. MonoBehaviour.print("连接服务器失败");
  52. return;
  53. }
  54. }
  55.  
  56. private static 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, , m_AllDataEnd - m_AllDataHead);
  62. System.Buffer.BlockCopy(mCurAllData, , m_AllData, , m_AllDataEnd - m_AllDataHead);
  63. m_AllDataEnd -= m_AllDataHead;
  64. m_AllDataHead = ;
  65. }
  66. int mOnePackStartPos = ;
  67. while (mReceiveNumber > )
  68. {
  69. if ( == 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, );
  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, , m_AllData, m_AllDataEnd, datalen);
  101. m_OnePackIndex = ;
  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 static void Destroy()
  118. {
  119. if (!m_HasInit)
  120. {
  121. return;
  122. }
  123. LanSocketBase.BaseRelease();
  124. ShutDownConnect();
  125. m_MsgNum = ;
  126. }
  127.  
  128. public static void GetMsg(ref MsgUnPack msg)
  129. {
  130. if (!m_HasInit)
  131. {
  132. return;
  133. }
  134. try
  135. {
  136. Lock();
  137. if ( != 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 static void ReceiveMessage()
  155. {
  156. while (true)
  157. {
  158. Thread.Sleep();
  159. try
  160. {
  161. //通过clientSocket接收数据
  162. byte[] mClientSendBuff = new byte[m_MaxOnePackBuff + ];
  163. int mReceiveNumber = m_Connect.Receive(mClientSendBuff);
  164. if ( == mReceiveNumber)
  165. {
  166. MonoBehaviour.print("disconnect");
  167. ShutDownConnect();
  168. }
  169. else if (mReceiveNumber > )
  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 static 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 static 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

支持类部分

  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 = * ;
  17. public static int m_MaxAllBuff = * ;
  18. public static int m_HeadSize = ;
  19. protected static bool m_HasInit = false;
  20. protected static byte[] m_OnePack;
  21. protected static int m_OnePackIndex;
  22. private static Mutex m_Mutex;
  23.  
  24. public static void BaseInit()
  25. {
  26. m_HasInit = true;
  27. m_Mutex = new Mutex();
  28. m_OnePack = new byte[m_MaxOnePackBuff+];
  29. m_OnePackIndex = ;
  30. }
  31.  
  32. public static void BaseRelease()
  33. {
  34. m_Mutex.Close();
  35. }
  36.  
  37. protected static void Lock()
  38. {
  39. m_Mutex.WaitOne();
  40. //MonoBehaviour.print("Lock:" + Thread.CurrentThread.ManagedThreadId.ToString());
  41. }
  42.  
  43. protected static void UnLock()
  44. {
  45. m_Mutex.ReleaseMutex();
  46. //MonoBehaviour.print("Unlock:" + Thread.CurrentThread.ManagedThreadId.ToString());
  47. }
  48. }
  49. }

LanSocketBase

  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 = ;
  24. }
  25. }
  26. }

PackBase.cs

  1. using UnityEngine;
  2. /*
  3. * 通信协议
  4. * 消息头前2字节保存当前消息长度
  5. * 后面跟4字节表示消息ID
  6. * 再后面是消息实质内容
  7. */
  8.  
  9. namespace LanSocket
  10. {
  11. 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, , m_OnePack, , );
  22. }
  23.  
  24. public void PackEnd()
  25. {
  26. byte[] mBuff = System.BitConverter.GetBytes(m_OnePackIndex);
  27. System.Buffer.BlockCopy(mBuff, , m_OnePack, , );
  28. }
  29.  
  30. public void Packbool(bool data)
  31. {
  32. ushort curDatalen = ;
  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 = ;
  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 = ;
  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 = ;
  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 = ;
  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 = ;
  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 = ;
  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 = ;
  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, , 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

  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, );
  22. m_MsgID = System.BitConverter.ToUInt16(m_OnePack, );
  23. m_OnePackIndex = ;
  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, , m_OnePack, , len);
  39. GetHead();
  40. }
  41.  
  42. public void UnPack(byte[] mBuff, ushort offset, ushort len)
  43. {
  44. System.Buffer.BlockCopy(mBuff, offset, m_OnePack, , len);
  45. GetHead();
  46. }
  47.  
  48. public bool Readbool()
  49. {
  50. if (m_OnePackIndex + > 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 + > m_PackLen)
  63. {
  64. MonoBehaviour.print("ReadShort() longer lager than Max buff len");
  65. return ;
  66. }
  67. short data = System.BitConverter.ToInt16(m_OnePack, m_OnePackIndex);
  68. m_OnePackIndex += ;
  69. return data;
  70. }
  71.  
  72. public ushort ReadUShort()
  73. {
  74. if (m_OnePackIndex + > m_PackLen)
  75. {
  76. MonoBehaviour.print("ReadUShortbit() longer lager than Max buff len");
  77. return ;
  78. }
  79. ushort data = System.BitConverter.ToUInt16(m_OnePack, m_OnePackIndex);
  80. m_OnePackIndex += ;
  81. return data;
  82. }
  83.  
  84. public int ReadInt()
  85. {
  86. if (m_OnePackIndex + > m_PackLen)
  87. {
  88. MonoBehaviour.print("ReadInt() longer lager than Max buff len");
  89. return ;
  90. }
  91. int data = System.BitConverter.ToInt32(m_OnePack, m_OnePackIndex);
  92. m_OnePackIndex += ;
  93. return data;
  94. }
  95.  
  96. public uint ReadUInt()
  97. {
  98. if (m_OnePackIndex + > m_PackLen)
  99. {
  100. MonoBehaviour.print("ReadUInt() longer lager than Max buff len");
  101. return ;
  102. }
  103. uint data = System.BitConverter.ToUInt32(m_OnePack, m_OnePackIndex);
  104. m_OnePackIndex += ;
  105. return data;
  106. }
  107.  
  108. public float ReadFloat()
  109. {
  110. if (m_OnePackIndex + > 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 += ;
  117. return data;
  118. }
  119.  
  120. public double ReadDouble()
  121. {
  122. if (m_OnePackIndex + > 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 += ;
  129. return data;
  130. }
  131.  
  132. public long ReadLong()
  133. {
  134. if (m_OnePackIndex + > m_PackLen)
  135. {
  136. MonoBehaviour.print("ReadLong() longer lager than Max buff len");
  137. return ;
  138. }
  139. long data = System.BitConverter.ToInt64(m_OnePack, m_OnePackIndex);
  140. m_OnePackIndex += ;
  141. return data;
  142. }
  143.  
  144. public ulong ReadULong()
  145. {
  146. if (m_OnePackIndex + > m_PackLen)
  147. {
  148. MonoBehaviour.print("ReadULong() longer lager than Max buff len");
  149. return ;
  150. }
  151. ulong data = System.BitConverter.ToUInt64(m_OnePack, m_OnePackIndex);
  152. m_OnePackIndex += ;
  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

  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 = -;
  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

  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. delegate void EventDelagate(LanSocket.ClientMsgUnPack msg);
  6.  
  7. class EventNode
  8. {
  9. public int m_EventID;
  10. public LanSocket.ClientMsgUnPack msg;
  11. }
  12.  
  13. class EventDispath
  14. {
  15. public static int g_MaxEventNum = ;
  16. List<EventDelagate>[] m_Event;
  17. Queue<EventNode> m_EventQueue;
  18. public EventDispath()
  19. {
  20. m_Event = new List<EventDelagate>[g_MaxEventNum];
  21. m_EventQueue = new Queue<EventNode>();
  22. }
  23.  
  24. public void RegistEvent(int eventID, EventDelagate func)
  25. {
  26. if(null == m_Event[eventID])
  27. {
  28. m_Event[eventID] = new List<EventDelagate>();
  29. }
  30. m_Event[eventID].Add(func);
  31. }
  32.  
  33. public void AddEvent(EventNode eventNode)
  34. {
  35. m_EventQueue.Enqueue(eventNode);
  36. }
  37.  
  38. public void Proccess()
  39. {
  40. if ( != m_EventQueue.Count)
  41. {
  42. EventNode mCur = m_EventQueue.Dequeue();
  43. if (null == m_Event[mCur.m_EventID])
  44. {
  45. MonoBehaviour.print("event ID: "+ mCur.m_EventID+" is null");
  46. }
  47. else
  48. {
  49. List<EventDelagate> curEventDelagate = m_Event[mCur.m_EventID];
  50. for(int i = ; i < curEventDelagate.Count ; ++i)
  51. {
  52. curEventDelagate[i](mCur.msg);
  53. }
  54. }
  55. }
  56. }
  57. }

EventDispath.cs

unity部分

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class ServerMain : MonoBehaviour
  5. {
  6. bool m_Destroy;
  7. EventDispath m_ClientMsg;
  8. void Start ()
  9. {
  10. m_Destroy = false;
  11. //服务器IP地址
  12. LanSocket.Server.Start();
  13. m_ClientMsg = new EventDispath();
  14. m_ClientMsg.RegistEvent(, Action_123);
  15.  
  16. }
  17.  
  18. // Update is called once per frame
  19. void Update ()
  20. {
  21. if(!m_Destroy)
  22. {
  23. LanSocket.ClientMsgUnPack clientMsg = null;
  24. LanSocket.Server.GetMsg(ref clientMsg);
  25. if (null != clientMsg)
  26. {
  27. print("Msg:" + clientMsg.GetMsgID() + " from: " + clientMsg.GetUserID());
  28.  
  29. EventNode mNode = new EventNode();
  30. mNode.m_EventID = clientMsg.GetMsgID(); ;
  31. mNode.msg = clientMsg;
  32. m_ClientMsg.AddEvent(mNode);
  33. }
  34.  
  35. m_ClientMsg.Proccess();
  36. }
  37. }
  38.  
  39. void OnDestroy()
  40. {
  41. m_Destroy = true;
  42. LanSocket.Server.Destroy();
  43. }
  44.  
  45. void Action_123(LanSocket.ClientMsgUnPack msg)
  46. {
  47. long userID = msg.GetUserID();
  48. ushort accountLen = msg.ReadUShort();
  49. string account = msg.ReadString(accountLen);
  50. ushort passLen = msg.ReadUShort();
  51. string pass = msg.ReadString(passLen);
  52.  
  53. print("Action_123 account: " + account + " pass word: " + pass+" from user: " + userID);
  54.  
  55. LanSocket.MsgPack sendMsg = new LanSocket.MsgPack();
  56. sendMsg.SetHead();
  57. string strAccount = "test account";
  58. sendMsg.Pack16bit((ushort)strAccount.Length);
  59. sendMsg.PackString(strAccount, (ushort)strAccount.Length);
  60. string strPass = "test pass word";
  61. sendMsg.Pack16bit((ushort)strPass.Length);
  62. sendMsg.PackString(strPass, (ushort)strPass.Length);
  63. sendMsg.PackEnd();
  64. LanSocket.Server.SendTo(ref sendMsg, msg.GetUserID());
  65. }
  66. }

ServerMain.cs

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class ClientMain : MonoBehaviour {
  5.  
  6. // Use this for initialization
  7. void Start ()
  8. {
  9. LanSocket.Client.Start();
  10. }
  11.  
  12. // Update is called once per frame
  13. void Update ()
  14. {
  15. LanSocket.MsgUnPack msg = null;
  16. LanSocket.Client.GetMsg(ref msg);
  17. if(null != msg)
  18. {
  19. print("here have one msg on client");
  20. }
  21.  
  22. if(Input.GetKeyUp(KeyCode.J))
  23. {
  24. LanSocket.MsgPack sendMsg = new LanSocket.MsgPack();
  25. sendMsg.SetHead();
  26. string strAccount = "test account";
  27. sendMsg.Pack16bit((ushort)strAccount.Length);
  28. sendMsg.PackString(strAccount, (ushort)strAccount.Length);
  29. string strPass = "test pass word";
  30. sendMsg.Pack16bit((ushort)strPass.Length);
  31. sendMsg.PackString(strPass, (ushort)strPass.Length);
  32. sendMsg.PackEnd();
  33. LanSocket.Client.Send(ref sendMsg);
  34. }
  35. }
  36. void OnDestroy()
  37. {
  38. LanSocket.Client.Destroy();
  39. }
  40. }

ClientMain.cs

以上为全部代码,拖到u3d项目中,然后将clientmain或servermain挂在对象上就可以运行了

c# socket select 模型代码(u3d)的更多相关文章

  1. u3d局域网游戏网络(c# socket select 模型)

    之前写了一篇. 发完之后第二天实际应用到游戏之后还是发现了一些小毛病. 比如网络模块有重复使用(多对象)的情况.所以将静态类该成了普通类. 比如安卓下会有些异常出现导致游戏逻辑不正常.所以网络相关的函 ...

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

    原文:http://www.cnblogs.com/saucerman/p/5555793.html 因为项目要加语音.语音数据都非常大.所以顺带就把之前写的网络模块一起测试了. 然后发现了一些bug ...

  3. socket select模型

    由于socket recv()方法是堵塞式的,当多个客户端连接服务器时,其中一个socket的recv调用时,会产生堵塞,使其他连接不能继续. 如果想改变这种一直等下去的焦急状态,可以多线程来实现(不 ...

  4. socket select()模型

    转载:http://www.cnblogs.com/xiangshancuizhu/archive/2012/10/05/2711882.html 由于socket recv()方法是阻塞式的,当有多 ...

  5. C# Socket select模型

    http://www.cnblogs.com/Clingingboy/archive/2011/07/04/2097806.html http://www.cnblogs.com/RascallySn ...

  6. 多路复用I/O模型select() 模型 代码实现

    多路复用I/O:  socket编程之select(),poll(),epoll() 代码: client.c #include <stdio.h> #include <sys/ty ...

  7. windows socket编程select模型使用

    int select(         int nfds,            //忽略         fd_ser* readfds,    //指向一个套接字集合,用来检测其可读性       ...

  8. socket编程的select模型

    在掌握了socket相关的一些函数后,套接字编程还是比较简单的,日常工作中碰到很多的问题就是客户端/服务器模型中,如何让服务端在同一时间高效的处理多个客户端的连接,我们的处理办法可能会是在服务端不停的 ...

  9. socket之 select模型

    前段时间一直想学习网络编程的select模型,看了<windows网络编程>的介绍,参考了别人的博客. 这里的资料主要来自http://www.cnblogs.com/RascallySn ...

随机推荐

  1. 20145214 《Java程序设计》第9周学习总结

    20145214 <Java程序设计>第9周学习总结 教材学习内容总结 JDBC简介 JDBC全名Java DataBase Connectivity,是java联机数据库的标准规范.它定 ...

  2. lintcode-184-最大数

    184-最大数 给出一组非负整数,重新排列他们的顺序把他们组成一个最大的整数. 注意事项 最后的结果可能很大,所以我们返回一个字符串来代替这个整数. #### 样例 给出 [1, 20, 23, 4, ...

  3. grid++json页面数据传入

    最近遇到一个问题,就是要用Grid++做页面数据报表打印,但是翻了Grid++文档就是没有直接从页面上传数据的,都是要加载txt文档,填写txt文档的url.自己尝试直接页面上传JSON数据到Grid ...

  4. 【week2】四人小组项目(WBS、NABCD)

    项目选题:东北师范大学论坛 小组名称:nice! 项目组长:李权 组员:于淼 刘芳芳 杨柳 本周任务:要求给出需求概述.功能列表.痛点或亮点.NABCD及WBS模型在此项目中的应用. 作为东北师范大学 ...

  5. PAT 1058 选择题

    https://pintia.cn/problem-sets/994805260223102976/problems/994805270356541440 批改多选题是比较麻烦的事情,本题就请你写个程 ...

  6. [转]Windows 7 蓝屏后获取 MEMORY.DMP 文件及注意事项

    转自:http://hi.baidu.com/guicomeon/item/d6753a177fc76f0f8fbde46a 系统默认会在 C:\Windows 目录下创建 MEMORY.DMP 文件 ...

  7. 安全的API接口解决方案

    在各种手机APP泛滥的现在,背后都有同样泛滥的API接口在支撑,其中鱼龙混杂,直接裸奔的WEB API大量存在,安全性令人堪优 在以前WEB API概念没有很普及的时候,都采用自已定义的接口和结构,对 ...

  8. WITH REPLACE 含义

    RESTORE DATABASE db_CSharp from disk='backup.bak' WITH REPLACE WITH REPLACE后面是限定条件,with replace意思是替换 ...

  9. linux下清空文件全部内容,如log日志

    在实际操作中经常需要清空log文件, 比如a.log,   有的人说, 直接删除不就行了, 但是, 直接删除后, 没法使用tail -f a.log了. 有的人说, 先rm再touch一个新文件不就可 ...

  10. Redis 学习之数据类型

    该文使用centos6.5 64位 redis-3.2.8 [root@localhost bin]# netstat -tunpl |grep 6379  查看redis 是否启动成功 一.Stri ...