uStreamCoderSocket.pas 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. unit uStreamCoderSocket;
  2. interface
  3. uses
  4. uICoderSocket, Classes, SysUtils, uZipTools;
  5. type
  6. {$if CompilerVersion < 18}
  7. TBytes = array of Byte;
  8. {$IFEND}
  9. TStreamCoderSocket = class(TObject)
  10. private
  11. class function SendStream(pvSocket: ICoderSocket; pvStream: TStream): Integer;
  12. public
  13. /// <summary>
  14. /// 接收解码
  15. /// </summary>
  16. /// <returns> Boolean
  17. /// </returns>
  18. /// <param name="pvSocket"> (TClientSocket) </param>
  19. /// <param name="pvObject"> (TObject) </param>
  20. class function RecvObject(pvSocket: ICoderSocket; pvObject: TObject): Boolean;
  21. /// <summary>
  22. /// 编码发送
  23. /// </summary>
  24. /// <param name="pvSocket"> (TClientSocket) </param>
  25. /// <param name="pvDataObject"> (TObject) </param>
  26. class function SendObject(pvSocket: ICoderSocket; pvObject: TObject): Integer;
  27. end;
  28. implementation
  29. //PACK_FLAG + CRC_VALUE + STREAM_LEN + STREAM_DATA
  30. uses
  31. uByteTools;
  32. const
  33. PACK_FLAG = $D10;
  34. MAX_OBJECT_SIZE = 1024 * 1024 * 10; //最大对象大小 10M , 大于10M 则会认为错误的包。
  35. const
  36. BUF_BLOCK_SIZE = 1024 * 8;
  37. resourcestring
  38. strRecvException_ErrorFlag = '错误的包头数据,断开与服务器的连接';
  39. strRecvException_ErrorData = '错误的数据,断开与服务器的连接';
  40. strRecvException_VerifyErr = '错误的数据包,校验失败!';
  41. strSendException_TooBig = '数据包太大,请在业务层分拆发送,最大数据包[%d]!';
  42. strSendException_NotEqual = '发送Buffer错误指定发送%d,实际发送:%d';
  43. { TStreamCoderSocket }
  44. class function TStreamCoderSocket.RecvObject(pvSocket: ICoderSocket;
  45. pvObject: TObject): Boolean;
  46. var
  47. lvBytes:TBytes;
  48. lvReadL, lvTempL:Integer;
  49. lvPACK_FLAG:Word;
  50. lvDataLen: Integer;
  51. lvVerifyValue, lvVerifyDataValue:Cardinal;
  52. lvPByte:PByte;
  53. begin
  54. pvSocket.recvBuf(@lvPACK_FLAG, 2);
  55. if lvPACK_FLAG <> PACK_FLAG then
  56. begin
  57. pvSocket.closeSocket;
  58. //错误的包数据
  59. raise Exception.Create(strRecvException_ErrorFlag);
  60. end;
  61. //veri value
  62. pvSocket.recvBuf(@lvVerifyValue, SizeOf(lvVerifyValue));
  63. //headlen
  64. pvSocket.recvBuf(@lvReadL, SizeOf(lvReadL));
  65. lvDataLen := TByteTools.swap32(lvReadL);
  66. //文件头不能过大
  67. if lvDataLen > MAX_OBJECT_SIZE then
  68. begin
  69. //错误的包数据
  70. pvSocket.closeSocket;
  71. //错误的包数据
  72. raise Exception.Create(strRecvException_ErrorData);
  73. end;
  74. SetLength(lvBytes,lvDataLen);
  75. lvPByte := PByte(@lvBytes[0]);
  76. lvReadL := 0;
  77. while lvReadL < lvDataLen do
  78. begin
  79. lvTempL := pvSocket.recvBuf(lvPByte, lvDataLen - lvReadL);
  80. if lvTempL = -1 then
  81. begin
  82. RaiseLastOSError;
  83. end;
  84. Inc(lvPByte, lvTempL);
  85. lvReadL := lvReadL + lvTempL;
  86. end;
  87. lvVerifyDataValue := TZipTools.verifyData(lvBytes[0], lvDataLen);
  88. if lvVerifyDataValue <> lvVerifyValue then
  89. begin
  90. raise Exception.Create(strRecvException_VerifyErr);
  91. end;
  92. TStream(pvObject).Write(lvBytes[0], lvDataLen);
  93. Result := true;
  94. end;
  95. class function TStreamCoderSocket.SendObject(pvSocket: ICoderSocket; pvObject:
  96. TObject): Integer;
  97. var
  98. lvPACK_FLAG: WORD;
  99. lvDataLen, lvWriteIntValue: Integer;
  100. lvBuf: TBytes;
  101. lvStream:TMemoryStream;
  102. lvVerifyValue:Cardinal;
  103. begin
  104. lvPACK_FLAG := PACK_FLAG;
  105. lvStream := TMemoryStream.Create;
  106. try
  107. TStream(pvObject).Position := 0;
  108. if TStream(pvObject).Size > MAX_OBJECT_SIZE then
  109. begin
  110. raise Exception.CreateFmt(strSendException_TooBig, [MAX_OBJECT_SIZE]);
  111. end;
  112. //pack_flag
  113. lvStream.Write(lvPACK_FLAG, 2);
  114. //
  115. lvDataLen := TStream(pvObject).Size;
  116. // stream data
  117. SetLength(lvBuf, lvDataLen);
  118. TStream(pvObject).Read(lvBuf[0], lvDataLen);
  119. //veri value
  120. lvVerifyValue := TZipTools.verifyData(lvBuf[0], lvDataLen);
  121. lvStream.Write(lvVerifyValue, SizeOf(lvVerifyValue));
  122. lvWriteIntValue := TByteTools.swap32(lvDataLen);
  123. // stream len
  124. lvStream.Write(lvWriteIntValue, SizeOf(lvWriteIntValue));
  125. // send pack
  126. lvStream.write(lvBuf[0], lvDataLen);
  127. Result := SendStream(pvSocket, lvStream);
  128. finally
  129. lvStream.Free;
  130. end;
  131. end;
  132. class function TStreamCoderSocket.SendStream(pvSocket: ICoderSocket; pvStream:
  133. TStream): Integer;
  134. var
  135. lvBufBytes:array[0..BUF_BLOCK_SIZE-1] of byte;
  136. l, j, r, lvTotal:Integer;
  137. P:PByte;
  138. begin
  139. Result := 0;
  140. if pvStream = nil then Exit;
  141. if pvStream.Size = 0 then Exit;
  142. lvTotal :=0;
  143. pvStream.Position := 0;
  144. repeat
  145. //FillMemory(@lvBufBytes[0], SizeOf(lvBufBytes), 0);
  146. l := pvStream.Read(lvBufBytes[0], SizeOf(lvBufBytes));
  147. if (l > 0) then
  148. begin
  149. P := PByte(@lvBufBytes[0]);
  150. j := l;
  151. while j > 0 do
  152. begin
  153. r := pvSocket.sendBuf(P, j);
  154. if r = -1 then
  155. begin
  156. RaiseLastOSError;
  157. end;
  158. Inc(P, r);
  159. Dec(j, r);
  160. end;
  161. lvTotal := lvTotal + l;
  162. end else Break;
  163. until (l = 0);
  164. Result := lvTotal;
  165. end;
  166. end.