I. Introduction▲
Les programmes de test sont présents dans le répertoire exemples accompagnant le présent document.
Depuis RADStudio XE6, il existe une bibliothèque de composants permettant aux applications qui les utilisent de communiquer aisément entre elles.
Si le nombre de cas d'utilisation est infini, on pourrait les catégoriser comme suit :
- application satellite : cas d'une application tierce, qui vient au service d'une application principale, et qui ne peut exister indépendamment de l'application principale (ex. : lanceur d'application, serveur d'impression) ;
- application complémentaire : cas d'une application tierce qui vient en complément d'une application principale, parce que l'application principale n'implémente pas la fonction (ex. : modem, application de prise de photo, application de prise de mesure via des capteurs/détecteurs) ;
- application entre pairs : cas d'une application qui communique avec ses pairs, une à une, ou une à plusieurs (ex. : application de messagerie instantanée, compteurs).
L'exemple traité ici sera un cas particulier d'une application de type « complémentaire » puisqu'il s'agira d'une application de partage de connexion Internet.
Le cas du partage d'une connexion Internet est le cas qui a donné son nom à tethering, à tel point que ce service est implémenté en standard par les systèmes d'exploitation quand, depuis un matériel ne disposant pas de connexion Web autonome, ce matériel décide de s'adresser à un autre matériel, généralement un téléphone portable, pour obtenir la connexion.
II. Présentation des composants impliqués▲
II-A. TtetheringManager▲
L'objectif du composant TTetheringManager est de gérer la connexion.
La propriété principale à utiliser est :
- AllowedAdapters : [Network|Bluetooth|Network_V4|NetWork_V6].
Comme son nom l'indique, elle permet de préciser l'adaptateur à utiliser. Par ailleurs, il est possible d'ajouter ses propres adaptateurs (Adapters). Pour plus de détails sur les Adapters, lire ceci.
II-B. TtetheringAppProfile▲
L'objectif du composant TTetheringAppProfile est d'encapsuler les ressources et les actions qui seront partagées au sein d'un même conteneur (le composant lui-même) ayant des règles communes de sécurité et d'accès aux « Ressources » et aux « Actions ».
Les principales propriétés de ce composant sont :
- Manager : cette propriété pointera sur le composant TTetheringManager décrit précédemment. Ainsi, un TTetheringManager pourra être associé à plusieurs TTetheringAppProfile ;
- Actions : il s'agit de la liste d'actions qu'il sera possible d'invoquer depuis l'application distante, ou bien des actions de l'application distante qu'il sera possible d'invoquer ;
- Resources : indique la liste des données qu'il sera possible de partager avec l'application distante. Ces données pourront être partagées de diverses manières : soit la donnée est envoyée, soit elle est demandée puis reçue, soit elle est écoutée ;
- Group : définit le nom d'un groupe au sein duquel toutes les applications possédant un TTetheringAppProfile avec le même nom de sa propriété Group, pourront entrer en communication automatiquement.
III. Application de partage de connexion Web▲
III-A. Principe général▲
Deux applications seront impliquées : une application demandeuse (dite client) et une application fournisseuse (dite WebProvider).
III-A-1. L'appariement des deux applications▲
L'appariement est le processus par lequel les deux applications vont se reconnaître, pour pouvoir communiquer.
Plusieurs techniques d'appariement sont à disposition :
1. Lappariement automatique, par l'appel de la méthode TTetheringManager.AutoConnect, et l'utilisation d'un TTetheringAppProfile.Group commun aux deux applications voulant s'apparier. C'est cette technique qui sera utilisée dans l'exemple ;
2. L'appariement manuel, par l'appel de la méthode TTetheringManager.DiscoverManagers, qui impliquera un processus de notification /réponses, où interviendront successivement les événements TTetheringManager.OnEndManagersDiscovery et TTetheringManager.OnEndProfilesDiscovery, pour se terminer par un appel à TTetheringAppProfile.Connect.
Par défaut, l'appariement est réalisé dans le LAN.
Cependant, il est possible d'établir un appariement « en dehors » du LAN, en utilisant le paramètre « Target » des méthodes TTetheringManager.AutoConnect ou TTetheringManager.DiscoverManagers.
III-A-2. L'application client▲
Cette application disposera de l'interface utilisateur afin de permettre à ce dernier de demander une page Web via son URL.
Pour communiquer cette information à l'application fournisseuse, les deux composants d'AppTethering seront nécessaires.
Seul le TTetheringAppProfile aura un événement à gérer, OnResourceReceived, celui qui surviendra quand l'application WebProvider lui enverra sa réponse.
Mis à part cet événement OnResourceReceived, les autres propriétés ne devront pas être modifiées.
III-A-3. L'application WebProvider▲
Cette application disposera de l'accès au Web afin de renvoyer au client le flux http relatif à sa requête, comme indiqué dans le paragraphe précédent.
Pour communiquer cette information à l'application client, les deux composants d'AppTethering seront là aussi nécessaires.
Ici aussi, seul le TTetheringAppProfile aura le même unique événement à gérer, OnResourceReceived, qui surviendra quand le client lui enverra sa requête.
Mis à part l'événement OnResourceReceived, les propriétés de ces composants n'ont pas à être modifiées.
III-B. Processus chronologique entre les deux applications▲
III-B-1. Du côté client▲
Avant d'envoyer la requête, une vérification de connexion devra être faite : le TTetheringManager est-il connecté à son pair, côté WebProvider ?
L'envoi de la requête est réalisé via l'événement choisi (par exemple, TAction.OnExecute, ou TButton.OnClick), avec la méthode SendString :
TTetheringAppProfile.SendString(aProfileInfo: TTetheringProfileInfo, aDescription: string
, aString: string
)
Les paramètres sont les suivants :
- aProfileInfo est le profil distant (par exemple, TetheringManager1.RemoteProfiles.Items[0]) ;
- aDescription est le nom de la ressource que le profil distant va recevoir ;
- aString est la chaîne « ressource », associée à aDescription, que le profil distant va recevoir.
Ex. : TetheringAppProfile1.SendString(TetheringManager1.RemoteProfiles.Items[0], 'URL', 'www.developpez.com').
AppTethering, outre l'envoi de données de type « String », via SendString, permet également d'envoyer des données de type TStream, à l'application tierce, comme nous le verrons plus tard, côté WebProvider.
III-B-2. Du côté WebProvider▲
Nous nous attendons à ce que cette application reçoive la requête envoyée par le Client.
Si elle arrive, cette requête parviendra par le biais de l'événement du WebProvider, OnResourceReceived, décrit en III.A.3.
Sur cet événement OnResourceReceived, il faudra traiter la requête et envoyer la réponse.
Le code suivant s'en chargera :
procedure
TForm2.TetheringAppProfile1ResourceReceived(const
Sender: TObject;
const
AResource: TRemoteResource);
var
lURL: string
;
SS: TStringStream;
begin
// si la ressource reçue est nommée "URL"
if
AResource.Hint = 'URL'
then
begin
lURL := AResource.Value.AsString;
SS := TStringStream.Create;
try
{ j'envoie le contenu de la ressource reçue (AResource.Value.AsString) comme paramètre au composant TidHHTP afin qu'il me retourne sa réponse (SS) }
idHTTP1.Get(AResource.Value.AsString, SS);
SS.Position := 0
;
{ quand la réponse (SS) est disponible, je renvoie cette réponse à l'application client et je la nomme "Response" }
if
not
TetheringAppProfile1.SendStream(TetheringManager1.RemoteProfiles.Items[0
]
, 'Response'
, SS) then
raise
Exception.Create('cannot send'
);
lbRequests.Items.Append(lURL);
finally
SS.Free;
end
;
end
;
end
;
III-B-3. De nouveau du côté Client▲
Nous nous attendons à ce que cette application, à son tour, reçoive la réponse, nommée 'Response', renvoyée par le WebProvider.
Si elle arrive, cette réponse parviendra par le biais de l'événement décrit en III.A.1, OnResourceReceived.
Le code suivant qui s'en chargera :
procedure
TfrmClient.TetheringAppProfile1ResourceReceived(const
Sender: TObject;
const
AResource: TRemoteResource);
var
SS: TStringStream;
s: string
;
begin
// si la ressource reçue est nommée "Response"
if
AResource.Hint = 'Response'
then
begin
SS := TStringStream.Create;
try
// je charge le contenu de cette ressource dans SS
SS.LoadFromStream(AResource.Value.AsStream);
// j'affiche SS dans un « Viewer » (TMemo ou THtmlViewer)
Memo1.Lines.LoadFromStream(SS);
finally
SS.Free;
end
;
end
;
end
;
IV. Les applications exemples▲
Afin de tester les exemples proposés, vous devrez tout d'abord installer les composants HtmlViewer 11.7 disponibles sur GitHub.
Le WebProvider est fourni sous VCL et FMX. Vous choisirez la version que vous préférez pour l'exécuter. Après avoir lancé le WebProvider, lancez alors le Client pour envoyer vos requêtes :
- connectez-vous avec le bouton Connect ;
- choisissez une URL depuis la TComboBox ;
- cliquez sur le bouton Go.
V. Conclusion▲
Cet exemple ne montre que très partiellement la puissance de cette technologie, mais elle simplifie indéniablement le développement d'applications impliquant la communication interapplications.
Cette problématique (communication interapplications) pouvait, dans les versions précédentes de RAD Studio, être appréhendée de différentes manières, parmi lesquelles :
- le système des messages qui envoient des données (wm_copydata) ;
- les techniques propriétaires (ex. : Microsoft utilise OLE, DDE) ;
- le mappage de fichiers ou de blocs mémoire ;
- l'appel de procédures distantes (RPC), avec DCOM ;
- les sockets ;
- le protocole HTTP.
De nombreux exemples d'AppTethering sont disponibles :
- dans les démonstrations livrées avec RADStudio ;
- auprès de nombreux contributeurs tels que Malcolm Groves et Stephen Ball.
Ce tutoriel conçu et rédigé par Didier Cabalé est proposé par la société Barnsten.
La relecture technique et la mise en forme ont été effectuées par gvasseur58. La relecture orthographique a été effectuée par Claude Leloup.