Service Discovery sample (Delphi)
Overview
This sample illustrates the usage of the broadcast UDP based service discovery with TRODiscoveryClient and TRODiscoveryServer components.
Note: This technology is deprecated, consider using ROZeroConf instead.
Each instance of the application acts as a server and a client at the same time.
For the server, you can modify the list of services supported on the right-hand side, while for the client you can enter a service name and get a list of the servers available on your LAN to support it.
Getting started
- The resulting application combines the client and the server, so in order to test this sample, you need to deploy the compiled .exe on two or more computers.
Note: If you are running a trial version of the Remoting SDK, you need to have the Delphi IDE running on each machine due to trial version limitations.
- Click
Discover Servers
on the client side and see the list of found servers with specified interfaces. - Change the Services list on the server side and try to discover servers with added or removed services.
- Uncheck the
Return info
checkbox for one of the servers and discover the servers again; see that no info is provided by the server. - Test the
Find a Server with a Load below
andSimulated Server Load
options, and see that clients won't discover servers with loads other than specified by the first one. - Uncheck/check the List registered RO Servers as supported checkbox and see that clients won't/will discover this server.
Examine the code
- Look how discovery query and result objects are defined to expand the TRODiscoveryOptions class:
TMyDiscoveryQueryOptions = class(TRODiscoveryOptions)
private
fMaximumLoad: Integer;
published
property MaximumLoad: Integer read fMaximumLoad write fMaximumLoad;
end;
TMyDiscoveryResultOptions = class(TRODiscoveryOptions)
private
fServerTime: TDateTime;
fMoreInfo: UnicodeString;
fLoad: Integer;
published
property ServerTime: TDateTime read fServerTime write fServerTime;
property MoreInfo: UnicodeString read fMoreInfo write fMoreInfo;
property Load: Integer read fLoad write fLoad;
end;
- In order to provide a custom list of service names that are available, the server uses the ServiceList string collection:
procedure TServiceDiscoveryMainForm.btn_UpdateServiceListClick(Sender: TObject);
begin
RODiscoveryServer.ServiceList.Assign(ed_Services.Lines);
end;
- See how the client looks for servers with the specified interface:
procedure TServiceDiscoveryMainForm.btn_LookupServiceClick(Sender: TObject);
var
lOptions: TMyDiscoveryQueryOptions;
begin
lb_Servers.Items.Clear();
RODiscoveryClient.ServiceName := ed_ServiceName.Text;
lOptions := TMyDiscoveryQueryOptions.Create();
try
lOptions.MaximumLoad := StrToIntDef(ed_MaxLoad.Text,100);
RODiscoveryClient.RefreshServerList(lOptions);
finally
lOptions.Free();
end;
end;
- If the server supports queried interfaces, the OnServiceFound event is fired allowing the server to evaluate the data and return the answer or refuse to return:
procedure TServiceDiscoveryMainForm.RODiscoveryServerServiceFound(
aSender: TObject; aName: string; var ioDiscoveryOptions: TRODiscoveryOptions;
var ioHandled: Boolean);
begin
if Assigned(ioDiscoveryOptions) and (ioDiscoveryOptions is TMyDiscoveryQueryOptions) then begin
{ Check if we fullfill the load requirement. If our load is too high, abort
without sending a response to the client }
if TMyDiscoveryQueryOptions(ioDiscoveryOptions).MaximumLoad <= StrToIntDef(ed_ServerLoad.Text,100) then begin
ROSendNoResponse();
end;
end;
if cb_ReturnInfo.Checked then begin
ioDiscoveryOptions := TMyDiscoveryResultOptions.Create;
with TMyDiscoveryResultOptions(ioDiscoveryOptions) do begin
Load := StrToIntDef(ed_ServerLoad.Text,-1);
MoreInfo := 'Some info';
ServerTime := Now;
end; { with }
end
else begin
ioDiscoveryOptions := nil;
end;
{ Don't free the original ioDiscoveryOptions (if it was assigned), the RO
framework takes care of that, just as it will free the one we pass back }
end;
- When a new server responds to the broadcast query, the OnNewServiceFound event is fired on the client and the server is added to the server list.
procedure TServiceDiscoveryMainForm.RODiscoveryClientNewServiceFound(
aSender: TObject; aName: String; aDiscoveryOptions: TRODiscoveryOptions);
var
lOptions: TMyDiscoveryResultOptions;
begin
if Assigned(aDiscoveryOptions) and (aDiscoveryOptions is TMyDiscoveryResultOptions) then begin
lOptions := TMyDiscoveryResultOptions(aDiscoveryOptions);
lb_Servers.Items.Add(Format('%s (Load: %d; Info: %s)',[aName, lOptions.Load, lOptions.MoreInfo]));
end
else begin
lb_Servers.Items.Add(aName+' (no info)');
end;
end;