ESocket.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Threading.Tasks;
  4. namespace ENet
  5. {
  6. public sealed class ESocket: IDisposable
  7. {
  8. private readonly ESocketEvent eSocketEvent = new ESocketEvent();
  9. private IntPtr peerPtr = IntPtr.Zero;
  10. private readonly IOService service;
  11. public ESocket(IOService service)
  12. {
  13. this.service = service;
  14. }
  15. public void Dispose()
  16. {
  17. if (this.peerPtr == IntPtr.Zero)
  18. {
  19. return;
  20. }
  21. NativeMethods.enet_peer_reset(this.peerPtr);
  22. this.peerPtr = IntPtr.Zero;
  23. }
  24. public IntPtr PeerPtr
  25. {
  26. get
  27. {
  28. return this.peerPtr;
  29. }
  30. set
  31. {
  32. this.peerPtr = value;
  33. }
  34. }
  35. private ENetPeer Struct
  36. {
  37. get
  38. {
  39. if (this.peerPtr == IntPtr.Zero)
  40. {
  41. return new ENetPeer();
  42. }
  43. return (ENetPeer) Marshal.PtrToStructure(this.peerPtr, typeof (ENetPeer));
  44. }
  45. set
  46. {
  47. Marshal.StructureToPtr(value, this.peerPtr, false);
  48. }
  49. }
  50. public ESocketEvent ESocketEvent
  51. {
  52. get
  53. {
  54. return this.eSocketEvent;
  55. }
  56. }
  57. public PeerState State
  58. {
  59. get
  60. {
  61. if (this.peerPtr == IntPtr.Zero)
  62. {
  63. return PeerState.Uninitialized;
  64. }
  65. return this.Struct.State;
  66. }
  67. }
  68. public void Ping()
  69. {
  70. NativeMethods.enet_peer_ping(this.peerPtr);
  71. }
  72. public void ConfigureThrottle(uint interval, uint acceleration, uint deceleration)
  73. {
  74. NativeMethods.enet_peer_throttle_configure(this.peerPtr, interval, acceleration, deceleration);
  75. }
  76. public Task<bool> ConnectAsync(
  77. string hostName, ushort port,
  78. uint channelLimit = NativeMethods.ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT,
  79. uint data = 0)
  80. {
  81. if (channelLimit > NativeMethods.ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
  82. {
  83. throw new ArgumentOutOfRangeException("channelLimit");
  84. }
  85. var tcs = new TaskCompletionSource<bool>();
  86. var address = new Address { HostName = hostName, Port = port };
  87. ENetAddress nativeAddress = address.Struct;
  88. this.peerPtr = NativeMethods.enet_host_connect(
  89. this.service.HostPtr, ref nativeAddress, channelLimit, data);
  90. if (this.peerPtr == IntPtr.Zero)
  91. {
  92. throw new ENetException("Host connect call failed.");
  93. }
  94. this.service.PeersManager.Add(this.peerPtr, this);
  95. this.ESocketEvent.Connected += e => tcs.TrySetResult(true);
  96. return tcs.Task;
  97. }
  98. public Task<bool> AcceptAsync()
  99. {
  100. if (this.service.PeersManager.ContainsKey(IntPtr.Zero))
  101. {
  102. throw new ENetException("Do Not Accept Twice!");
  103. }
  104. var tcs = new TaskCompletionSource<bool>();
  105. this.service.PeersManager.Add(this.PeerPtr, this);
  106. this.ESocketEvent.Connected += e => tcs.TrySetResult(true);
  107. return tcs.Task;
  108. }
  109. public void WriteAsync(byte[] data, byte channelID = 0, PacketFlags flags = PacketFlags.None)
  110. {
  111. var packet = new Packet(data, flags);
  112. NativeMethods.enet_peer_send(this.peerPtr, channelID, packet.PacketPtr);
  113. // enet_peer_send函数会自动删除packet,设置为0,防止Dispose或者析构函数再次删除
  114. packet.PacketPtr = IntPtr.Zero;
  115. }
  116. public Task<byte[]> ReadAsync()
  117. {
  118. var tcs = new TaskCompletionSource<byte[]>();
  119. this.ESocketEvent.Received += e =>
  120. {
  121. if (e.EventState == EventState.DISCONNECTED)
  122. {
  123. tcs.TrySetException(new ENetException("Peer Disconnected In Received"));
  124. }
  125. using (var packet = new Packet(e.PacketPtr))
  126. {
  127. var bytes = packet.Bytes;
  128. packet.Dispose();
  129. tcs.TrySetResult(bytes);
  130. }
  131. };
  132. return tcs.Task;
  133. }
  134. public Task<bool> DisconnectAsync(uint data = 0)
  135. {
  136. NativeMethods.enet_peer_disconnect(this.peerPtr, data);
  137. var tcs = new TaskCompletionSource<bool>();
  138. this.ESocketEvent.Disconnect += e => tcs.TrySetResult(true);
  139. return tcs.Task;
  140. }
  141. public Task<bool> DisconnectLaterAsync(uint data = 0)
  142. {
  143. NativeMethods.enet_peer_disconnect_later(this.peerPtr, data);
  144. var tcs = new TaskCompletionSource<bool>();
  145. this.ESocketEvent.Disconnect += e => tcs.TrySetResult(true);
  146. return tcs.Task;
  147. }
  148. public void DisconnectNow(uint data)
  149. {
  150. NativeMethods.enet_peer_disconnect_now(this.peerPtr, data);
  151. }
  152. }
  153. }