FAQ DelphiConsultez toutes les FAQ

Nombre d'auteurs : 123, nombre de questions : 920, dernière mise à jour : 8 novembre 2019  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums Delphi et Delphi et bases de données de www.developpez.com et de l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous souhaitez y apporter des corrections ou la compléter, contactez un responsable (lien au bas de cette page).

Nous espérons que cette FAQ saura répondre à vos attentes. Nous vous en souhaitons une bonne lecture.

L'équipe Delphi de Developpez.com.

Commentez


SommaireComposants IndyIndy 10 (6)
précédent sommaire suivant
 

La procédure suivante s'applique à Delphi 7 et 8.

La procédure d'installation des composants Indy 10 peut poser problème notamment l'erreur suivante lors de l'utilisation :

Code : Sélectionner tout
L'unité IdCustomTCPServer a été compilée avec une version différente de IdComponent.TIdComponent
Pour remédier à ce problème il suffit juste de suivre cette démarche pour l'installation :
  • Aller dans Ajout/Suppression de programmes.
  • Choisir Modifier du logiciel Delphi et décocher Indy dans Fichiers programme.
  • Installer les composants Indy 10.

Les composants sont dès à présent fonctionnels, vous pouvez relancer Delphi.

Mis à jour le 1er février 2014 Benjamin GAGNEUX

Sous Indy 9, la signature des événements était en général de la forme suivante :

Code Delphi : Sélectionner tout
procedure TformMain.IdTCPServer1Execute(AThread: TIdPeerThread);
Avec Indy 10, le paramètre transmis est de type différent :
Code Delphi : Sélectionner tout
procedure TformMain.IdTCPServer1Execute(AContext: TIdContext);
Comme on le voit, le type est passé de TIdPeerThread à TIdContext. En fait, les événements sont toujours exécutés dans un thread, mais il est possible qu'une même connexion soit exécutée à des moments différents par des threads différents. Par exemple, l'événement OnConnect peut être appelé depuis un thread, OnExecute depuis un autre, etc.
Or, dans les versions précédentes d'Indy, le thread étant unique, on pouvait y stocker des informations particulières (via sa propriété Data) ou y faire référence pour désigner un client. Comme Indy 10 n'assigne pas un unique thread à chaque connexion, cette association ne peut plus être effectuée.
Pour remplacer cela, Indy 10 fournir un "contexte" sous la forme du TIdContext. Cet objet est passé à chaque événement et est associé uniquement à une seule connexion. Cela ne représente pas la connexion en elle-même, mais des informations de session associées à la connexion. L'association est effectuée automatiquement par Indy.

Le TIdContext a une propriété Data comme la classe TIdPeerThread en avait une. Vous pouvez également créer des descendants personnalisés du TIdContext et dire au serveur de l'utiliser en utilisant la propriété ContextClass du serveur.

Mis à jour le 1er février 2014 Reisubar

Les précautions pour l'envoi d'un enregistrement avec Indy 10 sont les mêmes qu'avec Indy 9, à savoir, entre autres, longueur fixe et pas de pointeurs.
Par contre, du fait du support de .NET, les variables non typées ne sont plus supportées par la librairie. On peut cependant manipuler des octets en utilisant le type TIdBytes, qui n'est rien de plus qu'un tableau de bytes (array of byte). Par conséquent, il faudra transformer l'élément en TIdBytes pour ensuite utiliser les méthodes de lecture et d'écriture des sockets.

I) Côté client

Il y a deux manières de procéder :

1. Utiliser la fonction RawToBytes() de l'unité IdGlobal.

La fonction RawToBytes() permet de "convertir" une structure quelconque en TIdBytes. Le résultat de la conversion sera transmis à la fonction Write() de la propriété IOHandler du composant.

Dans le cas d'une structure quelconque :

Code Delphi : Sélectionner tout
1
2
3
4
5
  TClient = packed record 
    ID : Cardinal; 
    Name : string[20]; 
    IP : string[20]; 
  end;
...le code client peut s'écrire :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TForm1.Button1Click(Sender: TObject); 
var 
  LClient : TClient; 
begin 
  {On remplis l'enregistrement} 
  LClient.ID := 142; 
  LClient.Name := 'Jean Paul'; 
  LClient.IP := '82.51.127.2'; 
  {On se connecte, puis on l'envoie} 
  IdTCPClient1.Connect; 
  try 
    IdTCPClient1.IOHandler.Write(RawToBytes(LClient, SizeOf(LClient))); 
  finally 
    IdTCPClient1.Disconnect; 
  end; 
end;
2. On peut aussi remplir le buffer "manuellement" en utilisant SetLength et Move :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
procedure TForm1.Button1Click(Sender: TObject); 
var 
  LClient : TClient; 
  LBuffer : TIdBytes; 
begin 
  [...] 
  try 
    {Définir la taille du buffer} 
    SetLength(LBuffer, SizeOf(TClient)); 
    {Déplacer le contenu de la structure dans le buffer} 
    Move(LClient, LBuffer[0], SizeOf(TClient)); 
    {Envoyer...} 
    IdTCPClient1.IOHandler.Write(LBuffer); 
  finally 
    IdTCPClient1.Disconnect; 
  end; 
end;
II) Côté serveur

La démarche est inverse : Définir la taille du buffer de type TIdBytes en fonction de la structure à recevoir, lire des données dans le buffer, puis déplacer le contenu du buffer dans la structure réceptrice :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); 
var 
  LClient : TClient; 
  LBuffer : TIdBytes; 
begin 
  {Définir la taille du buffer} 
  SetLength(LBuffer, SizeOf(TClient)); 
  {Lire} 
  AContext.Connection.IOHandler.ReadBytes(LBuffer, SizeOf(TClient), False); 
  {Déplacer} 
  Move(LBuffer[0],LClient,SizeOf(TClient)); 
  {Afficher (test)} 
  MessageBox(Handle, PChar(Format('Bonjour %s',[LClient.Name])), nil, 0); 
end;

Mis à jour le 1er février 2014 Reisubar

L'utilisation de flux (streams) sous Indy 10 a été revue et est différente de ce qu'elle était sous Indy 9. On doit maintenant passer par une "enveloppe" de type TIdStreamVCL.

Le constructeur de cette classe attend en paramètre un TStream à contenir. Le second paramètre, de type booléen, spécifie si le flux original doit être détruit ou pas à la destruction de l'objet "enveloppe". Le flux original peut être accédé via la propriété VCLStream du TIdStreamVCL.

Exemple 1 : Utilisation du TIdStreamVCL avec un flux existant. Le second paramètre, à false, indique que le flux existant devra être détruit manuellement (il est donc indépendant de son enveloppe). On voit ici que le flux original et le flux pointé par la propriété VCLStream du TIdStreamVCL sont les mêmes :

Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
procedure TForm1.Button2Click(Sender: TObject); 
var 
  LStream : TStream; 
  LWrapper : TIdStreamVCL; 
  Buffer : array [0..512] of char; 
begin 
  LStream := TMemoryStream.Create; 
  LWrapper := TIdStreamVCL.Create(LStream, False); 
  try 
    {Initialisation du buffer} 
    StrPCopy(Buffer, 'Hello, World !'); 
    {Ecriture dans le stream originel} 
    LStream.Seek(0, soFromBeginning); 
    LStream.Write(Buffer[0], SizeOf(Buffer)); 
    {RAZ du buffer} 
    FillChar(Buffer, SizeOf(Buffer), #0); 
    {On le relit à partir du stream "contenu" par l'enveloppe LWrapper} 
    LWrapper.VCLStream.Seek(0, soFromBeginning); 
    LWrapper.VCLStream.Read(Buffer[0], SizeOf(Buffer)); 
    {Affichage du contenu du buffer} 
    MessageDlg(String(Buffer), mtInformation, [mbOK], 0); 
    {MessageDlg affiche bien "Hello World" => OK} 
  finally 
    FreeAndNil(LStream); 
    FreeAndNil(LWrapper); 
  end; 
end;
Exemple 2 : Utilisation d'une TIdStreamVCL avec un flux créé à la volée. On appelle ensuite une version de la méthode Write(), en lui passant le TIdStreamVCL suivi de l'entier 0, qui signifie qu'on souhaite envoyer tout le flux au serveur :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
procedure TForm1.Button3Click(Sender: TObject); 
var 
  LWrapper : TIdStreamVCL; 
Begin 
  {Crée le TIdStreamVCL à partir d'un TFileStream ouvert sur "c:\test.txt"} 
  LWrapper := TIdStreamVCL.Create(TFileStream.Create('c:\test.txt',fmOpenRead), True); 
  Try 
    {Ecrire le flux} 
    IdTCPClient1.IOHandler.Write(LWrapper, 0); 
  finally 
    FreeAndNil(LWrapper); 
  end;
Exemple 3 : Exemple d'envoi de flux entre un client et un serveur.

Client :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
procedure TForm1.Button3Click(Sender: TObject); 
var 
  LWrapper : TIdStreamVCL; 
  LStreamSize : int64; 
begin 
  IdTCPClient1.Connect; 
  try 
    LWrapper := TIdStreamVCL.Create(TFileStream.Create('c:\test.txt',fmOpenRead), True); 
    try 
      {Récupérer la taille du flux original} 
      LStreamSize := LWrapper.VCLStream.Size; 
      {Envoyer la taille} 
      IdTCPClient1.IOHandler.Write(LStreamSize); 
      {Envoyer le flux} 
      IdTCPClient1.IOHandler.Write(LWrapper, 0); 
    finally 
      FreeAndNil(LWrapper); 
    end; 
  finally 
    IdTCPClient1.Disconnect; 
  end; 
end;
Serveur :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); 
var 
  LStreamSize : int64; 
  LWrapper : TIdStreamVCL; 
begin 
  {Lire la taille transmise} 
  LStreamSize := AContext.Connection.IOHandler.ReadInt64(); 
  try 
    {Créer le flux de destination} 
    LWrapper := TIdStreamVCL.Create(TFileStream.Create('c:\resultat.txt', fmCreate), True); 
    try 
      {Lire le flux} 
      AContext.Connection.IOHandler.ReadStream(LWrapper, LStreamSize); 
    finally 
      FreeAndNil(LWrapper); 
    end; 
  finally 
  end; 
end;

Mis à jour le 1er février 2014 Reisubar

Toutes les fonctions de lecture et d'envoi d'octets bruts (comme Read(), ReadLn(), Write(), WriteLn()) sont maintenant déplacés dans l'objet TIdIOHandler, à la place de TIdTCPConnection. Dans la majorité des cas, la mise à jour n'est pas très difficile. Il suffit d'insérer IOHandler devant l'appel à la fonction d'entrée/sortie.

Exemple pour un client :

Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
procedure TForm1.Button1Click(Sender: TObject); 
var 
  LBuffer : TIdBytes; 
begin 
  [...]     
  IdTCPClient1.IOHandler.Write(LBuffer); 
  [...]     
end;
Pour un serveur :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); 
var 
  LBuffer : TIdBytes; 
Begin 
[...] 
  AContext.Connection.IOHandler.ReadBytes(LBuffer, SizeOf(TClient), False); 
[...] 
end;

Mis à jour le 1er février 2014 Reisubar

Dans Indy 9, les TIdTCPServer contenaient tout le code et les propriétés nécessaires pour supporter le fonctionnement des CommandHandlers. Avec Indy 10, ces fonctionnalités ont été séparées dans un composant nommé TIdCmdTCPServer qui descend du TIdTCPServer. Ainsi, les serveurs n'utilisant pas cette approche pourront ne pas inclure systématiquement le code relatif à la gestion de ce système.

Par conséquent, l'ancien TIdTCPServer est maintenant équivalent au composant TIdCmdTCPServer dans Indy 10. Cela introduit un problème dans les fichiers DFM quand d'anciens projets sont chargés : Delphi chargera le TIdTCPServer avec moins de propriétés.
Si vous n'utilisez pas les CommandHandlers, vous pouvez cliquer sur "tout ignorer" lorsque l'IDE vous demandera comment mettre à jour le fichier DFM. Sinon, vous devrez éditer manuellement le(s) fichier(s) DFM faisant référence aux anciens TIdTCPServer pour changer leur type à TIdCmdTCPServer.

Mis à jour le 26 janvier 2014 Reisubar

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2019 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.