UPoller.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. using System;
  2. using System.Collections.Generic;
  3. namespace UNet
  4. {
  5. public sealed class UPoller: IDisposable
  6. {
  7. static UPoller()
  8. {
  9. Library.Initialize();
  10. }
  11. private readonly PeersManager peersManager = new PeersManager();
  12. private readonly LinkedList<UEvent> connEEvents = new LinkedList<UEvent>();
  13. internal PeersManager PeersManager
  14. {
  15. get
  16. {
  17. return this.peersManager;
  18. }
  19. }
  20. internal LinkedList<UEvent> ConnEEvents
  21. {
  22. get
  23. {
  24. return this.connEEvents;
  25. }
  26. }
  27. private IntPtr host;
  28. private readonly object eventsLock = new object();
  29. private Action events;
  30. public UPoller(string hostName, ushort port)
  31. {
  32. UAddress address = new UAddress { HostName = hostName, Port = port };
  33. ENetAddress nativeAddress = address.Struct;
  34. this.host = NativeMethods.EnetHostCreate(
  35. ref nativeAddress, NativeMethods.ENET_PROTOCOL_MAXIMUM_PEER_ID, 0, 0, 0);
  36. if (this.host == IntPtr.Zero)
  37. {
  38. throw new UException("Host creation call failed.");
  39. }
  40. }
  41. public UPoller()
  42. {
  43. this.host = NativeMethods.EnetHostCreate(
  44. IntPtr.Zero, NativeMethods.ENET_PROTOCOL_MAXIMUM_PEER_ID, 0, 0, 0);
  45. if (this.host == IntPtr.Zero)
  46. {
  47. throw new UException("Host creation call failed.");
  48. }
  49. }
  50. ~UPoller()
  51. {
  52. this.Dispose(false);
  53. }
  54. public void Dispose()
  55. {
  56. this.Dispose(true);
  57. GC.SuppressFinalize(this);
  58. }
  59. private void Dispose(bool disposing)
  60. {
  61. if (this.host == IntPtr.Zero)
  62. {
  63. return;
  64. }
  65. NativeMethods.EnetHostDestroy(this.host);
  66. this.host = IntPtr.Zero;
  67. }
  68. public IntPtr HostPtr
  69. {
  70. get
  71. {
  72. return this.host;
  73. }
  74. }
  75. private UEvent GetEvent()
  76. {
  77. ENetEvent eEvent = new ENetEvent();
  78. int ret = NativeMethods.EnetHostCheckEvents(this.host, eEvent);
  79. if (ret <= 0)
  80. {
  81. return null;
  82. }
  83. UEvent u = new UEvent(eEvent);
  84. return u;
  85. }
  86. public void CompressWithRangeCoder()
  87. {
  88. NativeMethods.EnetHostCompressWithRangeCoder(this.host);
  89. }
  90. public void DoNotCompress()
  91. {
  92. NativeMethods.EnetHostCompress(this.host, IntPtr.Zero);
  93. }
  94. public void Flush()
  95. {
  96. NativeMethods.EnetHostFlush(this.host);
  97. }
  98. public void SetBandwidthLimit(uint incomingBandwidth, uint outgoingBandwidth)
  99. {
  100. NativeMethods.EnetHostBandwidthLimit(this.host, incomingBandwidth, outgoingBandwidth);
  101. }
  102. public void SetChannelLimit(uint channelLimit)
  103. {
  104. if (channelLimit > NativeMethods.ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
  105. {
  106. throw new ArgumentOutOfRangeException(string.Format("channelLimit: {0}", channelLimit));
  107. }
  108. NativeMethods.EnetHostChannelLimit(this.host, channelLimit);
  109. }
  110. public event Action Events
  111. {
  112. add
  113. {
  114. lock (this.eventsLock)
  115. {
  116. this.events += value;
  117. }
  118. }
  119. remove
  120. {
  121. lock (this.eventsLock)
  122. {
  123. this.events -= value;
  124. }
  125. }
  126. }
  127. public void OnEvents()
  128. {
  129. Action local = null;
  130. lock (this.eventsLock)
  131. {
  132. if (this.events == null)
  133. {
  134. return;
  135. }
  136. local = this.events;
  137. this.events = null;
  138. }
  139. local();
  140. }
  141. private int Service(int timeout)
  142. {
  143. if (timeout < 0)
  144. {
  145. throw new ArgumentOutOfRangeException(string.Format("timeout: {0}", timeout));
  146. }
  147. return NativeMethods.EnetHostService(this.host, null, (uint) timeout);
  148. }
  149. public void RunOnce(int timeout = 0)
  150. {
  151. if (timeout < 0)
  152. {
  153. throw new ArgumentOutOfRangeException(string.Format("timeout: {0}", timeout));
  154. }
  155. this.OnEvents();
  156. if (this.Service(timeout) < 0)
  157. {
  158. return;
  159. }
  160. while (true)
  161. {
  162. UEvent uEvent = this.GetEvent();
  163. if (uEvent == null)
  164. {
  165. return;
  166. }
  167. switch (uEvent.Type)
  168. {
  169. case EventType.Connect:
  170. {
  171. // 这是一个connect peer
  172. if (this.PeersManager.ContainsKey(uEvent.PeerPtr))
  173. {
  174. USocket uSocket = this.PeersManager[uEvent.PeerPtr];
  175. uSocket.OnConnected(uEvent);
  176. }
  177. // accept peer
  178. else
  179. {
  180. // 如果server端没有acceptasync,则请求放入队列
  181. if (!this.PeersManager.ContainsKey(IntPtr.Zero))
  182. {
  183. this.connEEvents.AddLast(uEvent);
  184. }
  185. else
  186. {
  187. USocket uSocket = this.PeersManager[IntPtr.Zero];
  188. uSocket.OnConnected(uEvent);
  189. }
  190. }
  191. break;
  192. }
  193. case EventType.Receive:
  194. {
  195. USocket uSocket = this.PeersManager[uEvent.PeerPtr];
  196. uSocket.OnReceived(uEvent);
  197. break;
  198. }
  199. case EventType.Disconnect:
  200. {
  201. // 如果链接还在缓存中,则删除
  202. foreach (UEvent connEEvent in this.connEEvents)
  203. {
  204. if (connEEvent.PeerPtr != uEvent.PeerPtr)
  205. {
  206. continue;
  207. }
  208. this.connEEvents.Remove(connEEvent);
  209. return;
  210. }
  211. // 链接已经被应用层接收
  212. uEvent.EventState = EventState.DISCONNECTED;
  213. USocket uSocket = this.PeersManager[uEvent.PeerPtr];
  214. this.PeersManager.Remove(uEvent.PeerPtr);
  215. // 等待的task将抛出异常
  216. if (uSocket.Connected != null)
  217. {
  218. uSocket.OnConnected(uEvent);
  219. }
  220. else if (uSocket.Received != null)
  221. {
  222. uSocket.OnReceived(uEvent);
  223. }
  224. else if (uSocket.Disconnect != null)
  225. {
  226. uSocket.OnDisconnect(uEvent);
  227. }
  228. uSocket.OnError(ErrorCode.ClientDisconnect);
  229. break;
  230. }
  231. }
  232. }
  233. }
  234. public void Run(int timeout = 0)
  235. {
  236. while (true)
  237. {
  238. this.RunOnce(timeout);
  239. }
  240. }
  241. }
  242. }