HttpClientDataHandlingAdapter.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. //------------------------------------------------------------------------------
  2. // 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
  3. // 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
  4. // CSDN博客:https://blog.csdn.net/qq_40374647
  5. // 哔哩哔哩视频:https://space.bilibili.com/94253567
  6. // Gitee源代码仓库:https://gitee.com/RRQM_Home
  7. // Github源代码仓库:https://github.com/RRQM
  8. // API首页:https://www.yuque.com/rrqm/touchsocket/index
  9. // 交流QQ群:234762506
  10. // 感谢您的下载和使用
  11. //------------------------------------------------------------------------------
  12. //------------------------------------------------------------------------------
  13. using System;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. using TouchSocket.Core;
  17. using TouchSocket.Sockets;
  18. namespace TouchSocket.Http
  19. {
  20. /// <summary>
  21. /// Http客户端数据处理适配器
  22. /// </summary>
  23. public class HttpClientDataHandlingAdapter : NormalDataHandlingAdapter
  24. {
  25. /// <summary>
  26. /// 缓存数据,如果需要手动释放,请先判断,然后到调用<see cref="IDisposable.Dispose"/>后,再置空;
  27. /// </summary>
  28. protected ByteBlock tempByteBlock;
  29. private static readonly byte[] m_rnCode = Encoding.UTF8.GetBytes("\r\n");
  30. private HttpResponse m_httpResponse;
  31. private long m_surLen;
  32. private Task m_task;
  33. /// <summary>
  34. /// <inheritdoc/>
  35. /// </summary>
  36. public override bool CanSplicingSend => false;
  37. /// <summary>
  38. /// <inheritdoc/>
  39. /// </summary>
  40. /// <param name="byteBlock"></param>
  41. protected override void PreviewReceived(ByteBlock byteBlock)
  42. {
  43. if (tempByteBlock == null)
  44. {
  45. byteBlock.Pos = 0;
  46. Single(byteBlock, false);
  47. }
  48. else
  49. {
  50. tempByteBlock.Write(byteBlock.Buffer, 0, byteBlock.Len);
  51. ByteBlock block = tempByteBlock;
  52. tempByteBlock = null;
  53. block.Pos = 0;
  54. Single(block, true);
  55. }
  56. }
  57. private void Cache(ByteBlock byteBlock)
  58. {
  59. if (byteBlock.CanReadLen > 0)
  60. {
  61. tempByteBlock = new ByteBlock();
  62. tempByteBlock.Write(byteBlock.Buffer, byteBlock.Pos, byteBlock.CanReadLen);
  63. if (tempByteBlock.Len > MaxPackageSize)
  64. {
  65. OnError("缓存的数据长度大于设定值的情况下未收到解析信号");
  66. }
  67. }
  68. }
  69. private FilterResult ReadChunk(ByteBlock byteBlock)
  70. {
  71. int position = byteBlock.Pos;
  72. int index = byteBlock.Buffer.IndexOfFirst(byteBlock.Pos, byteBlock.CanReadLen, m_rnCode);
  73. if (index > 0)
  74. {
  75. int headerLength = index - byteBlock.Pos;
  76. string hex = Encoding.ASCII.GetString(byteBlock.Buffer, byteBlock.Pos, headerLength - 1);
  77. int count = hex.ByHexStringToInt32();
  78. byteBlock.Pos += headerLength + 1;
  79. if (count >= 0)
  80. {
  81. if (count > byteBlock.CanReadLen)
  82. {
  83. byteBlock.Pos = position;
  84. return FilterResult.Cache;
  85. }
  86. m_httpResponse.InternalInput(byteBlock.Buffer, byteBlock.Pos, count);
  87. byteBlock.Pos += count;
  88. byteBlock.Pos += 2;
  89. return FilterResult.GoOn;
  90. }
  91. else
  92. {
  93. byteBlock.Pos += 2;
  94. return FilterResult.Success;
  95. }
  96. }
  97. else
  98. {
  99. return FilterResult.Cache;
  100. }
  101. }
  102. private void Single(ByteBlock byteBlock, bool dis)
  103. {
  104. try
  105. {
  106. while (byteBlock.CanReadLen > 0)
  107. {
  108. if (m_httpResponse == null)
  109. {
  110. m_httpResponse = new HttpResponse(Client, false);
  111. if (m_httpResponse.ParsingHeader(byteBlock, byteBlock.CanReadLen))
  112. {
  113. byteBlock.Pos++;
  114. if (m_httpResponse.IsChunk || m_httpResponse.ContentLength > byteBlock.CanReadLength)
  115. {
  116. m_surLen = m_httpResponse.ContentLength;
  117. m_task = EasyTask.Run(m_httpResponse, (res) =>
  118. {
  119. GoReceived(null, res);
  120. });
  121. }
  122. else
  123. {
  124. byteBlock.Read(out byte[] buffer, (int)m_httpResponse.ContentLength);
  125. m_httpResponse.SetContent(buffer);
  126. GoReceived(null, m_httpResponse);
  127. m_httpResponse = null;
  128. }
  129. }
  130. else
  131. {
  132. Cache(byteBlock);
  133. m_httpResponse = null;
  134. m_task?.Wait();
  135. m_task = null;
  136. return;
  137. }
  138. }
  139. if (m_httpResponse != null)
  140. {
  141. if (m_httpResponse.IsChunk)
  142. {
  143. switch (ReadChunk(byteBlock))
  144. {
  145. case FilterResult.Cache:
  146. Cache(byteBlock);
  147. return;
  148. case FilterResult.Success:
  149. m_httpResponse = null;
  150. m_task?.Wait();
  151. m_task = null;
  152. break;
  153. case FilterResult.GoOn:
  154. default:
  155. break;
  156. }
  157. }
  158. else if (m_surLen > 0)
  159. {
  160. if (byteBlock.CanRead)
  161. {
  162. int len = (int)Math.Min(m_surLen, byteBlock.CanReadLength);
  163. m_httpResponse.InternalInput(byteBlock.Buffer, byteBlock.Pos, len);
  164. m_surLen -= len;
  165. byteBlock.Pos += len;
  166. if (m_surLen == 0)
  167. {
  168. m_httpResponse.InternalInput(null, 0, 0);
  169. m_httpResponse = null;
  170. m_task?.Wait();
  171. m_task = null;
  172. }
  173. }
  174. }
  175. else
  176. {
  177. m_httpResponse = null;
  178. m_task?.Wait();
  179. m_task = null;
  180. }
  181. }
  182. }
  183. }
  184. finally
  185. {
  186. if (dis)
  187. {
  188. byteBlock.Dispose();
  189. }
  190. }
  191. }
  192. }
  193. }