InputChannel.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System;
  2. using System.Threading.Tasks;
  3. using Vinno.IUS.Common.IO;
  4. using Vinno.IUS.Common.Network.Tcp;
  5. namespace Vinno.IUS.Common.Network.Channels
  6. {
  7. /// <summary>
  8. ///For Client, the InputChannel must be availabe, otherwise it means the connection is abort, need reconnect.
  9. ///For server, it's not need to care about it. because the client's InputChannel is Server's output.
  10. /// </summary>
  11. public sealed class InputChannel : ClientChannel, IInputChannel
  12. {
  13. /// <summary>
  14. /// Raised when buffer received.
  15. /// </summary>
  16. public event EventHandler<IBuffer> BufferReceived;
  17. public InputChannel(int channelId, ITcp tcp)
  18. : base(channelId, tcp)
  19. {
  20. }
  21. /// <summary>
  22. /// Start receive data from network.
  23. /// </summary>
  24. internal void StartReceive()
  25. {
  26. Receive();
  27. }
  28. /// <summary>
  29. /// Start receive data from network in async way.
  30. /// </summary>
  31. /// <returns></returns>
  32. internal async Task StartReceiveAsync()
  33. {
  34. while (!IsClosed)
  35. {
  36. await ReceiveAsync().ConfigureAwait(false);
  37. }
  38. }
  39. /// <summary>
  40. /// Method to receive data from network,
  41. /// Use async can save the thread resource of system.
  42. /// </summary>
  43. private void Receive()
  44. {
  45. Task.Run(() =>
  46. {
  47. while (!IsClosed)
  48. {
  49. try
  50. {
  51. var buffer = DoReceive();
  52. OnBufferReceived(buffer);
  53. }
  54. catch (Exception ex)
  55. {
  56. var convertedException = NetworkException.Convert(ex);
  57. if (!(convertedException is ConnectionTimeoutException))
  58. {
  59. Close();
  60. }
  61. }
  62. }
  63. });
  64. }
  65. /// <summary>
  66. /// Method to receive data from network,
  67. /// Use async can save the thread resource of system.
  68. /// </summary>
  69. private async Task ReceiveAsync()
  70. {
  71. try
  72. {
  73. var buffer = await DoReceiveAsync().ConfigureAwait(false);
  74. OnBufferReceived(buffer);
  75. }
  76. catch (Exception ex)
  77. {
  78. var convertedException = NetworkException.Convert(ex);
  79. if (!(convertedException is ConnectionTimeoutException))
  80. {
  81. Close();
  82. }
  83. }
  84. }
  85. /// <summary>
  86. /// Receive buffer.
  87. /// The steps is :
  88. /// 1. Validate the Header.
  89. /// 2. Receive the buffer.
  90. /// </summary>
  91. /// <returns></returns>
  92. private IBuffer DoReceive()
  93. {
  94. ReadHeader();
  95. return ReadBuffer();
  96. }
  97. /// <summary>
  98. /// Receive buffer.
  99. /// The steps is :
  100. /// 1. Validate the Header.
  101. /// 2. Receive the buffer.
  102. /// </summary>
  103. /// <returns></returns>
  104. private async Task<IBuffer> DoReceiveAsync()
  105. {
  106. await ReadHeaderAsync().ConfigureAwait(false);
  107. return await ReadBufferAsync().ConfigureAwait(false);
  108. }
  109. /// <summary>
  110. /// Handler of pushed buffer.
  111. /// </summary>
  112. /// <param name="e"></param>
  113. private void OnBufferReceived(IBuffer e)
  114. {
  115. BufferReceived?.Invoke(this, e);
  116. }
  117. public override string ToString()
  118. {
  119. return $"InputChannel-{base.ToString()}";
  120. }
  121. }
  122. }