USocket.cs 3.0 KB

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