📄 rtcdatacli.pas
字号:
Leave HyperThreading as FALSE to use this component "the stadard way" (for example,
when you're writing a client application where requests are posted from the main thread
or if you are creating a separate component for every thread that needs it). }
property HyperThreading:boolean read FHyperThreading write FHyperThreading default False;
{ Set this property to a value other than 0 (zero) if you want the DataRequest to
auto-repost any request up to "AutoRepost" times, in case the connection gets lost
while sending data to server or receiving data from server.
AutoRepost = -1 means that request should be reposted infinitely. }
property AutoRepost:integer read FAutoRepost write FAutoRepost default 0;
{ This event will be called when DataClient component is
ready to start sending the request out.
@html(<br><br>)
If the request is already in memory (not a large file on disk),
send it out using Sender's WriteHeader and/or Write methods.
If the request is too large to be sent out at once (maybe a big file
on disk), you should at least send the Request Header out in this event.
@html(<br><br>)
If you DO NOT call Write and/or WriteHeader from this event,
then this Request will be skipped by the DataClient. }
property OnBeginRequest:TRtcNotifyEvent read FOnBeginRequest write FOnBeginRequest;
{ This event will be called after each DataReceived event for this request
and can be used to access info prepared by the OnDataReceived event. }
property OnResponseData:TRtcNotifyEvent read FOnResponseData write FOnResponseData;
{ This event will be called after the last DataReceived event for this request,
read after the request has been sent out and a complete response was received (Response.Done). }
property OnResponseDone:TRtcNotifyEvent read FOnResponseDone write FOnResponseDone;
{ This event will be called after ConnectLost, ConnectFail and ConnectError events if request was not marked for reposting.
If you want to re-post the request, you should call Request.Repost from
this event, or the Request will NOT be reposted and OnResponseAbort
event will be trigered. You can also use the AutoRepost property to tell the
component to repost requests automaticaly (for a specified number of times or unlimited). }
property OnRepostCheck:TRtcNotifyEvent read FOnRepostCheck write FOnRepostCheck;
{ This event will be called after the OnRepostCheck event if request was not marked for reposting. }
property OnResponseAbort:TRtcNotifyEvent read FOnResponseAbort write FOnResponseAbort;
{ This event will be called after the response has been rejected by calling Response.Reject }
property OnResponseReject:TRtcNotifyEvent read FOnResponseReject write FOnResponseReject;
{ This event will be called after a new Session has been opened. }
property OnSessionOpen:TRtcNotifyEvent read FOnSessionOpen write FOnSessionOpen;
{ This event will be called before an existing Session is about to close. }
property OnSessionClose:TRtcNotifyEvent read FOnSessionClose write FOnSessionClose;
{ This event will be mapped as TRtcDataClient.OnDataReceived event
to the assigned DataClient component and called for all DataReceived
events until the request is processed in full, skipped or rejected. }
property OnDataReceived:TRtcNotifyEvent read FOnDataReceived write FOnDataReceived;
{ This event will be mapped as @Link(TRtcConnection.OnDataOut) event
to the assigned DataClient component and called for all DataOut
events until the request is processed in full, skipped or rejected. }
property OnDataOut:TRtcNotifyEvent read FOnDataOut write FOnDataOut;
{ This event will be mapped as @Link(TRtcConnection.OnDataIn) event
to the assigned DataClient component and called for all DataIn
events until the request is processed in full, skipped or rejected. }
property OnDataIn:TRtcNotifyEvent read FOnDataIn write FOnDataIn;
{ This event will be mapped as @Link(TRtcConnection.OnDataSent) event
to the assigned DataClient component and called for all DataSent
events until the request is processed in full, skipped or rejected. }
property OnDataSent:TRtcNotifyEvent read FOnDataSent write FOnDataSent;
{ This event will be mapped as @Link(TRtcConnection.OnReadyToSend) event
to the assigned DataClient component and called for all ReadyToSend
events until the request is processed in full, skipped or rejected. }
property OnReadyToSend:TRtcNotifyEvent read FOnReadyToSend write FOnReadyToSend;
{ This event will be mapped as @Link(TRtcClient.OnConnectLost) event
to the assigned DataClient component and called if your connection gets
closed while you are processing your request (sending or receiving data).
@html(<br><br>)
If you want to re-send the request, you can call Request.Repost from this event,
or use the OnRepostCheck or OnResponseAborted events to do so. }
property OnConnectLost:TRtcNotifyEvent read FOnConnectLost write FOnConnectLost;
end;
implementation
type
{ @abstract(DataRequest Job)
This Job is used by TRtcDataClient to post a signal to start a request
@exclude }
TRtcStartRequestJob=class(TRtcJob)
Client:TRtcDataClient;
procedure Kill; override;
procedure Run(Thr:TRtcThread); override;
end;
{ TRtcDataClientLinkList }
constructor TRtcDataClientLinkList.Create;
begin
inherited;
FList:=TList.Create;
end;
destructor TRtcDataClientLinkList.Destroy;
begin
FList.Free;
inherited;
end;
procedure TRtcDataClientLinkList.Add(Value: TRtcAbsDataClientLink);
var
idx:integer;
begin
idx:=FList.IndexOf(Value);
if idx<0 then
FList.Add(Value);
end;
function TRtcDataClientLinkList.Count: integer;
begin
Result:=FList.Count;
end;
function TRtcDataClientLinkList.Get(index:integer): TRtcAbsDataClientLink;
begin
if (index>=0) and (index<FList.Count) then
Result:=TRtcAbsDataClientLink(FList.Items[index])
else
Result:=nil;
end;
procedure TRtcDataClientLinkList.Remove(Value: TRtcAbsDataClientLink);
var
idx:integer;
begin
idx:=FList.IndexOf(Value);
if idx>=0 then
FList.Delete(idx);
end;
procedure TRtcDataClientLinkList.RemoveAll;
begin
FList.Clear;
end;
{ TRtcDataClient }
constructor TRtcDataClient.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FMyRequest:=TRtcClientRequest.Create;
FMyResponse:=TRtcClientResponse.Create;
FRequest:=FMyRequest;
FResponse:=FMyResponse;
FCS:=TRtcCritSec.Create;
FSession:=TRtcClientSession.Create;
FSession.FCon:=self;
FMayInsertRequest:=False;
FRequestInserted:=False;
FDataClientLinks:=TRtcDataClientLinkList.Create;
FRequestList:=TList.Create;
FActiveRequest:=nil;
FIdle:=True;
FRequestSkipped:=0;
end;
destructor TRtcDataClient.Destroy;
begin
RemoveAllDataClientLinks;
FDataClientLinks.Free;
FDataClientLinks:=nil;
if assigned(FRequestList) then
begin
RemoveAllRequests;
RemoveRequest;
FRequestList.Free;
FRequestList:=nil;
end;
FActiveRequest:=nil;
FIdle:=True;
FMyRequest.Free; FRequest:=nil;
FMyResponse.Free; FResponse:=nil;
FSession.Free;
FCS.Free;
inherited;
end;
procedure TRtcDataClient.CallConnect;
begin
inherited;
if MultiThreaded then
PostStartRequest
else
StartRequest;
end;
procedure TRtcDataClient.CallReadyToSend;
begin
if assigned(FActiveRequest) then
begin
FActiveRequest.Call_ReadyToSend(self);
Flush;
CheckRequestWork;
end
else
inherited;
end;
procedure TRtcDataClient.CallDataSent;
begin
if assigned(FActiveRequest) then
begin
FActiveRequest.Call_DataSent(self);
Flush;
CheckRequestWork;
end
else
inherited;
end;
procedure TRtcDataClient.CallDataOut;
begin
if assigned(FActiveRequest) then
FActiveRequest.Call_DataOut(self);
inherited;
Flush;
end;
procedure TRtcDataClient.CallDataIn;
begin
if assigned(FActiveRequest) then
FActiveRequest.Call_DataIn(self);
inherited;
end;
procedure TRtcDataClient.CallDataReceived;
begin
if assigned(FActiveRequest) then
begin
FActiveRequest.Call_DataReceived(self);
Flush;
if CheckRequestWork then Exit;
FActiveRequest.Call_ResponseData(self);
Flush;
if CheckRequestWork then Exit;
if assigned(Request.OnData) then
begin
Request.OnData(self);
Flush;
if CheckRequestWork then Exit;
end;
if Response.Done then
begin
FActiveRequest.Call_ResponseDone(self);
if CheckRequestWork then Exit;
if assigned(Request.OnDone) then
Request.OnDone(self);
if CheckRequestWork then Exit;
RemoveRequest;
if MultiThreaded then
PostStartRequest
else
StartRequest;
end;
end
else
inherited;
end;
procedure TRtcDataClient.CallConnectLost;
begin
if assigned(FActiveRequest) then
begin
FActiveRequest.Call_ConnectLost(self);
if not Response.Done and not Request.Reposting then
begin
FActiveRequest.Call_RepostCheck(self);
if not Response.Done and not Request.Reposting then
begin
FActiveRequest.Call_ResponseAbort(self);
if assigned(Request.OnAbort) then
if not Request.Reposting then
Request.OnAbort(self);
end;
end;
inherited;
if Request.Skipped then
RemoveRequest
else if Response.Rejected then
begin
FActiveRequest.Call_ResponseReject(self);
if assigned(Request.OnReject) then
Request.OnReject(self);
RemoveRequest;
end
else if Request.Reposting then
begin
Request.Reposting:=False;
Response.Clear;
end
else if Response.Done then
RemoveRequest
else
begin
RemoveRequest;
// We will skip all remaining requests
CancelRequests;
end;
// This will remove all skipped requests
PrepareNextRequest;
end
else
inherited;
end;
procedure TRtcDataClient.CallConnectFail;
begin
PrepareNextRequest;
if assigned(FActiveRequest) then
begin
FActiveRequest.Call_RepostCheck(self);
if not Response.Done and not Request.Reposting then
begin
FActiveRequest.Call_ResponseAbort(self);
if assigned(Request.OnAbort) then
if not Request.Reposting then
Request.OnAbort(self);
end;
inherited;
if Request.Skipped then
RemoveRequest
else if Response.Rejected then
begin
FActiveRequest.Call_ResponseReject(self);
if assigned(Request.OnReject) then
Request.OnReject(self);
RemoveRequest;
end
else if Request.Reposting then
begin
Request.Reposting:=False;
Response.Clear;
end
else if Response.Done then
RemoveRequest
else
begin
RemoveRequest;
// We will skip all remaining requests
CancelRequests;
end;
// This will remove all skipped requests
PrepareNextRequest;
end
else
inherited;
end;
procedure TRtcDataClient.CallConnectError(E:Exception);
begin
PrepareNextRequest;
if assigned(FActiveRequest) then
begin
FActiveRequest.Call_RepostCheck(self);
if not Response.Done and not Request.Reposting then
begin
FActiveRequest.Call_ResponseAbort(self);
if assigned(Request.OnAbort) then
if not Request.Reposting then
Request.OnAbort(self);
end;
inherited;
if Request.Skipped then
RemoveRequest
else if Response.Rejected then
begin
FActiveRequest.Call_ResponseReject(self);
if assigned(Request.OnReject) then
Request.OnReject(self);
RemoveRequest;
end
else if Request.Reposting then
begin
Request.Reposting:=False;
Response.Clear;
end
else if Response.Done then
RemoveRequest
else
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -