2
0

IdUDPBase.pas 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 10407: IdUDPBase.pas
  11. {
  12. { Rev 1.0 2002.11.12 10:58:48 PM czhower
  13. }
  14. unit IdUDPBase;
  15. interface
  16. uses
  17. Classes,
  18. IdComponent, IdException, IdGlobal, IdSocketHandle;
  19. const
  20. ID_UDP_BUFFERSIZE = 8192;
  21. type
  22. TIdUDPBase = class(TIdComponent)
  23. protected
  24. FBinding: TIdSocketHandle;
  25. FBufferSize: Integer;
  26. FDsgnActive: Boolean;
  27. FHost: String;
  28. FPort: Integer;
  29. FReceiveTimeout: Integer;
  30. //
  31. FBroadcastEnabled: Boolean;
  32. procedure BroadcastEnabledChanged; dynamic;
  33. procedure CloseBinding; virtual;
  34. function GetActive: Boolean; virtual;
  35. procedure SetActive(const Value: Boolean);
  36. procedure SetBroadcastFlag(const Enabled: Boolean; ABinding: TIdSocketHandle = nil);
  37. procedure SetBroadcastEnabled(const Value: Boolean);
  38. function GetBinding: TIdSocketHandle; virtual;
  39. procedure Loaded; override;
  40. public
  41. constructor Create(AOwner: TComponent); override;
  42. destructor Destroy; override;
  43. //
  44. property Binding: TIdSocketHandle read GetBinding;
  45. procedure Broadcast(const AData: string; const APort: integer);
  46. function ReceiveBuffer(var ABuffer; const ABufferSize: Integer;
  47. const AMSec: Integer = IdTimeoutDefault): integer; overload;
  48. function ReceiveBuffer(var ABuffer; const ABufferSize: Integer; var VPeerIP: string;
  49. var VPeerPort: integer; AMSec: Integer = IdTimeoutDefault): integer; overload;
  50. function ReceiveString(const AMSec: Integer = IdTimeoutDefault): string; overload;
  51. function ReceiveString(var VPeerIP: string; var VPeerPort: integer;
  52. const AMSec: Integer = IdTimeoutDefault): string; overload;
  53. procedure Send(AHost: string; const APort: Integer; const AData: string);
  54. procedure SendBuffer(AHost: string; const APort: Integer; var ABuffer;
  55. const AByteCount: integer);
  56. //
  57. property ReceiveTimeout: Integer read FReceiveTimeout write FReceiveTimeout default IdTimeoutInfinite;
  58. published
  59. property Active: Boolean read GetActive write SetActive Default False;
  60. property BufferSize: Integer read FBufferSize write FBufferSize default ID_UDP_BUFFERSIZE;
  61. property BroadcastEnabled: Boolean read FBroadcastEnabled write SetBroadcastEnabled Default False;
  62. end;
  63. EIdUDPException = Class(EIdException);
  64. EIdUDPReceiveErrorZeroBytes = class(EIdUDPException);
  65. implementation
  66. uses
  67. IdResourceStrings, IdStack, IdStackConsts, SysUtils;
  68. { TIdUDPBase }
  69. procedure TIdUDPBase.Broadcast(const AData: string; const APort: integer);
  70. begin
  71. SetBroadcastFlag(True);
  72. Send('255.255.255.255', APort, AData); {Do not Localize}
  73. BroadcastEnabledChanged;
  74. end;
  75. procedure TIdUDPBase.BroadcastEnabledChanged;
  76. begin
  77. SetBroadcastFlag(BroadcastEnabled);
  78. end;
  79. procedure TIdUDPBase.CloseBinding;
  80. begin
  81. FreeAndNil(FBinding);
  82. end;
  83. constructor TIdUDPBase.Create(AOwner: TComponent);
  84. begin
  85. inherited;
  86. BufferSize := ID_UDP_BUFFERSIZE;
  87. FReceiveTimeout := IdTimeoutInfinite;
  88. end;
  89. destructor TIdUDPBase.Destroy;
  90. begin
  91. Active := False;
  92. inherited;
  93. end;
  94. function TIdUDPBase.GetActive: Boolean;
  95. begin
  96. Result := FDsgnActive or (Assigned(FBinding) and FBinding.HandleAllocated);
  97. end;
  98. function TIdUDPBase.GetBinding: TIdSocketHandle;
  99. begin
  100. if not Assigned(FBinding)then begin
  101. FBinding := TIdSocketHandle.Create(nil);
  102. end;
  103. if not FBinding.HandleAllocated then begin
  104. FBinding.AllocateSocket(Id_SOCK_DGRAM);
  105. BroadcastEnabledChanged;
  106. end;
  107. result := FBinding;
  108. end;
  109. procedure TIdUDPBase.Loaded;
  110. var
  111. b: Boolean;
  112. begin
  113. inherited;
  114. b := FDsgnActive;
  115. FDsgnActive := False;
  116. Active := b;
  117. end;
  118. function TIdUDPBase.ReceiveBuffer(var ABuffer; const ABufferSize: Integer;
  119. const AMSec: Integer): Integer;
  120. var
  121. VoidIP: string;
  122. VoidPort: Integer;
  123. begin
  124. Result := ReceiveBuffer(ABuffer, ABufferSize, VoidIP, VoidPort, AMSec);
  125. end;
  126. function TIdUDPBase.ReceiveBuffer(var ABuffer; const ABufferSize: Integer;
  127. var VPeerIP: string; var VPeerPort: integer;
  128. AMSec: Integer = IdTimeoutDefault): integer;
  129. begin
  130. if AMSec = IdTimeoutDefault then begin
  131. AMSec := ReceiveTimeOut;
  132. end;
  133. if not Binding.Readable(AMSec) then begin
  134. Result := 0;
  135. VPeerIP := ''; {Do not Localize}
  136. VPeerPort := 0;
  137. Exit;
  138. end;
  139. Result := Binding.RecvFrom(ABuffer, ABufferSize, 0, VPeerIP, VPeerPort);
  140. GStack.CheckForSocketError(Result);
  141. end;
  142. function TIdUDPBase.ReceiveString(var VPeerIP: string; var VPeerPort: integer;
  143. const AMSec: Integer = IdTimeoutDefault): string;
  144. var
  145. i: integer;
  146. begin
  147. SetLength(Result, BufferSize);
  148. i := ReceiveBuffer(Result[1], Length(Result), VPeerIP, VPeerPort, AMSec);
  149. SetLength(Result, i);
  150. end;
  151. function TIdUDPBase.ReceiveString(const AMSec: Integer): string;
  152. var
  153. VoidIP: string;
  154. VoidPort: Integer;
  155. begin
  156. result := ReceiveString(VoidIP, VoidPort, AMSec);
  157. end;
  158. procedure TIdUDPBase.Send(AHost: string; const APort: Integer; const AData: string);
  159. begin
  160. SendBuffer(AHost, APort, PChar(AData)^, Length(AData));
  161. end;
  162. procedure TIdUDPBase.SendBuffer(AHost: string; const APort: Integer; var ABuffer;
  163. const AByteCount: integer);
  164. begin
  165. AHost := GStack.ResolveHost(AHost);
  166. Binding.SendTo(AHost, APort, ABuffer, AByteCount);
  167. end;
  168. procedure TIdUDPBase.SetActive(const Value: Boolean);
  169. begin
  170. if (Active <> Value) then begin
  171. if not ((csDesigning in ComponentState) or (csLoading in ComponentState)) then begin
  172. if Value then begin
  173. GetBinding;
  174. end
  175. else begin
  176. CloseBinding;
  177. end;
  178. end
  179. else begin // don't activate at designtime (or during loading of properties) {Do not Localize}
  180. FDsgnActive := Value;
  181. end;
  182. end;
  183. end;
  184. procedure TIdUDPBase.SetBroadcastEnabled(const Value: Boolean);
  185. begin
  186. if FBroadCastEnabled <> Value then begin
  187. FBroadcastEnabled := Value;
  188. if Active then begin
  189. BroadcastEnabledChanged;
  190. end;
  191. end;
  192. end;
  193. procedure TIdUDPBase.SetBroadcastFlag(const Enabled: Boolean; ABinding: TIdSocketHandle = nil);
  194. var
  195. BroadCastData: LongBool;
  196. begin
  197. BroadCastData := Enabled;
  198. if ABinding = nil then begin
  199. ABinding := Binding;
  200. end;
  201. ABinding.SetSockOpt(Id_SOL_SOCKET, Id_SO_BROADCAST, PChar(@BroadCastData), SizeOf(BroadCastData));
  202. end;
  203. end.