USocket.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  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. private readonly Queue<byte[]> recvQueue = new Queue<byte[]>();
  16. private readonly Queue<BufferInfo> sendQueue = new Queue<BufferInfo>();
  17. private bool isConnected;
  18. public Action Disconnect;
  19. public TaskCompletionSource<USocket> AcceptTcs { private get; set; }
  20. public USocket(IntPtr peerPtr, UPoller poller)
  21. {
  22. this.poller = poller;
  23. this.PeerPtr = peerPtr;
  24. }
  25. public USocket(UPoller poller)
  26. {
  27. this.poller = poller;
  28. }
  29. public void Dispose()
  30. {
  31. if (this.PeerPtr == IntPtr.Zero)
  32. {
  33. return;
  34. }
  35. poller.USocketManager.Remove(this.PeerPtr);
  36. NativeMethods.ENetPeerDisconnectNow(this.PeerPtr, 0);
  37. this.PeerPtr = IntPtr.Zero;
  38. }
  39. public IntPtr PeerPtr { get; set; }
  40. public string RemoteAddress { get; private set; }
  41. public Queue<byte[]> RecvQueue
  42. {
  43. get
  44. {
  45. return recvQueue;
  46. }
  47. }
  48. public void ConnectAsync(string host, ushort port)
  49. {
  50. this.RemoteAddress = host + ":" + port;
  51. UAddress address = new UAddress(host, port);
  52. ENetAddress nativeAddress = address.Struct;
  53. this.PeerPtr = NativeMethods.ENetHostConnect(this.poller.Host, ref nativeAddress, 2, 0);
  54. if (this.PeerPtr == IntPtr.Zero)
  55. {
  56. throw new Exception($"host connect call failed, {host}:{port}");
  57. }
  58. this.poller.USocketManager.Add(this.PeerPtr, this);
  59. }
  60. public void SendAsync(byte[] data, byte channelID = 0, PacketFlags flags = PacketFlags.Reliable)
  61. {
  62. if (!isConnected)
  63. {
  64. sendQueue.Enqueue(new BufferInfo { Buffer = data, ChannelID = channelID, Flags = flags });
  65. return;
  66. }
  67. UPacket packet = new UPacket(data, flags);
  68. NativeMethods.ENetPeerSend(this.PeerPtr, channelID, packet.PacketPtr);
  69. // enet_peer_send函数会自动删除packet,设置为0,防止Dispose或者析构函数再次删除
  70. packet.PacketPtr = IntPtr.Zero;
  71. }
  72. internal void OnConnected()
  73. {
  74. isConnected = true;
  75. while (this.sendQueue.Count > 0)
  76. {
  77. BufferInfo info = this.sendQueue.Dequeue();
  78. this.SendAsync(info.Buffer, info.ChannelID, info.Flags);
  79. }
  80. }
  81. internal void OnAccepted(ENetEvent eEvent)
  82. {
  83. isConnected = true;
  84. if (eEvent.Type == EventType.Disconnect)
  85. {
  86. this.AcceptTcs.TrySetException(new Exception("socket disconnected in accpet"));
  87. }
  88. this.poller.USocketManager.Remove(IntPtr.Zero);
  89. USocket socket = new USocket(eEvent.Peer, this.poller);
  90. this.poller.USocketManager.Add(socket.PeerPtr, socket);
  91. this.AcceptTcs.TrySetResult(socket);
  92. }
  93. internal void OnReceived(ENetEvent eNetEvent)
  94. {
  95. // 将包放到缓存队列
  96. using (UPacket packet = new UPacket(eNetEvent.Packet))
  97. {
  98. byte[] bytes = packet.Bytes;
  99. this.RecvQueue.Enqueue(bytes);
  100. }
  101. }
  102. internal void OnDisconnect(ENetEvent eNetEvent)
  103. {
  104. Disconnect();
  105. }
  106. }
  107. }