PacketParser.cs 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System;
  2. namespace Base
  3. {
  4. internal enum ParserState
  5. {
  6. PacketSize,
  7. PacketBody
  8. }
  9. internal class PacketParser
  10. {
  11. private readonly TBuffer buffer;
  12. private uint packetSize;
  13. private readonly byte[] packetSizeBuffer = new byte[4];
  14. private ParserState state;
  15. private byte[] packet;
  16. private bool isOK;
  17. public PacketParser(TBuffer buffer)
  18. {
  19. this.buffer = buffer;
  20. }
  21. private void Parse()
  22. {
  23. if (this.isOK)
  24. {
  25. return;
  26. }
  27. bool finish = false;
  28. while (!finish)
  29. {
  30. switch (this.state)
  31. {
  32. case ParserState.PacketSize:
  33. if (this.buffer.Count < 4)
  34. {
  35. finish = true;
  36. }
  37. else
  38. {
  39. this.buffer.RecvFrom(this.packetSizeBuffer);
  40. this.packetSize = BitConverter.ToUInt32(this.packetSizeBuffer, 0);
  41. if (packetSize > 1024 * 1024)
  42. {
  43. throw new Exception($"packet too large, size: {this.packetSize}");
  44. }
  45. this.state = ParserState.PacketBody;
  46. }
  47. break;
  48. case ParserState.PacketBody:
  49. if (this.buffer.Count < this.packetSize)
  50. {
  51. finish = true;
  52. }
  53. else
  54. {
  55. this.packet = new byte[this.packetSize];
  56. this.buffer.RecvFrom(this.packet);
  57. this.isOK = true;
  58. this.state = ParserState.PacketSize;
  59. finish = true;
  60. }
  61. break;
  62. }
  63. }
  64. }
  65. public byte[] GetPacket()
  66. {
  67. this.Parse();
  68. if (!this.isOK)
  69. {
  70. return null;
  71. }
  72. byte[] result = this.packet;
  73. this.isOK = false;
  74. return result;
  75. }
  76. }
  77. }