USocket.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net;
  4. using System.Runtime.InteropServices;
  5. namespace Base
  6. {
  7. internal class BufferInfo
  8. {
  9. public byte[] Buffer { get; set; }
  10. public byte ChannelID { get; set; }
  11. public PacketFlags Flags { get; set; }
  12. }
  13. internal sealed class USocket: IDisposable
  14. {
  15. private readonly UPoller poller;
  16. public IntPtr PeerPtr { get; set; }
  17. private readonly Queue<byte[]> recvQueue = new Queue<byte[]>();
  18. private readonly Queue<BufferInfo> sendQueue = new Queue<BufferInfo>();
  19. private bool isConnected;
  20. private Action disconnect;
  21. private Action received;
  22. public event Action Received
  23. {
  24. add
  25. {
  26. this.received += value;
  27. }
  28. remove
  29. {
  30. this.received -= value;
  31. }
  32. }
  33. public event Action Disconnect
  34. {
  35. add
  36. {
  37. this.disconnect += value;
  38. }
  39. remove
  40. {
  41. this.disconnect -= value;
  42. }
  43. }
  44. public USocket(IntPtr peerPtr, UPoller poller)
  45. {
  46. this.poller = poller;
  47. this.PeerPtr = peerPtr;
  48. }
  49. public USocket(UPoller poller)
  50. {
  51. this.poller = poller;
  52. }
  53. public void Dispose()
  54. {
  55. if (this.PeerPtr == IntPtr.Zero)
  56. {
  57. return;
  58. }
  59. poller.USocketManager.Remove(this.PeerPtr);
  60. NativeMethods.enet_peer_disconnect_now(this.PeerPtr, 0);
  61. this.PeerPtr = IntPtr.Zero;
  62. }
  63. public string RemoteAddress
  64. {
  65. get
  66. {
  67. ENetPeer peer = this.Struct;
  68. IPAddress ipaddr = new IPAddress(peer.Address.Host);
  69. return $"{ipaddr}:{peer.Address.Port}";
  70. }
  71. }
  72. private ENetPeer Struct
  73. {
  74. get
  75. {
  76. if (this.PeerPtr == IntPtr.Zero)
  77. {
  78. return new ENetPeer();
  79. }
  80. ENetPeer peer = (ENetPeer)Marshal.PtrToStructure(this.PeerPtr, typeof(ENetPeer));
  81. return peer;
  82. }
  83. set
  84. {
  85. Marshal.StructureToPtr(value, this.PeerPtr, false);
  86. }
  87. }
  88. public Queue<byte[]> RecvQueue
  89. {
  90. get
  91. {
  92. return recvQueue;
  93. }
  94. }
  95. public void ConnectAsync(string host, ushort port)
  96. {
  97. UAddress address = new UAddress(host, port);
  98. ENetAddress nativeAddress = address.Struct;
  99. this.PeerPtr = NativeMethods.enet_host_connect(this.poller.Host, ref nativeAddress, 2, 0);
  100. if (this.PeerPtr == IntPtr.Zero)
  101. {
  102. throw new Exception($"host connect call failed, {host}:{port}");
  103. }
  104. this.poller.USocketManager.Add(this.PeerPtr, this);
  105. }
  106. public void SendAsync(byte[] data, byte channelID = 0, PacketFlags flags = PacketFlags.Reliable)
  107. {
  108. if (this.PeerPtr == IntPtr.Zero)
  109. {
  110. throw new Exception($"USocket 已经被Dispose,不能发送数据!");
  111. }
  112. if (!isConnected)
  113. {
  114. sendQueue.Enqueue(new BufferInfo { Buffer = data, ChannelID = channelID, Flags = flags });
  115. return;
  116. }
  117. UPacket packet = new UPacket(data, flags);
  118. NativeMethods.enet_peer_send(this.PeerPtr, channelID, packet.PacketPtr);
  119. // enet_peer_send函数会自动删除packet,设置为0,防止Dispose或者析构函数再次删除
  120. packet.PacketPtr = IntPtr.Zero;
  121. }
  122. internal void OnConnected()
  123. {
  124. isConnected = true;
  125. while (this.sendQueue.Count > 0)
  126. {
  127. BufferInfo info = this.sendQueue.Dequeue();
  128. this.SendAsync(info.Buffer, info.ChannelID, info.Flags);
  129. }
  130. }
  131. internal void OnAccepted()
  132. {
  133. isConnected = true;
  134. }
  135. internal void OnReceived(ENetEvent eNetEvent)
  136. {
  137. // 将包放到缓存队列
  138. using (UPacket packet = new UPacket(eNetEvent.Packet))
  139. {
  140. byte[] bytes = packet.Bytes;
  141. this.RecvQueue.Enqueue(bytes);
  142. }
  143. this.received();
  144. }
  145. internal void OnDisconnect(ENetEvent eNetEvent)
  146. {
  147. disconnect();
  148. }
  149. }
  150. }