IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

Lister les adresses IP builder starter


Sujet :

C++Builder

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2014
    Messages
    130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 130
    Points : 59
    Points
    59
    Par défaut Lister les adresses IP builder starter
    Bonjour,

    J'utilise Indy TIdTCPServer1 pour un projet de connexion serveur/client, notamment la pile GStack pour vérifier si une IP est valide ou lister les IP locales

    Le code ci-dessous envoie l'erreur suivante : "Erreur de vérification d'étendue".

    Visiblement cela vient de la boucle for. J'ai essayé .RefCount()-1, pas d'erreur mais cela ne fonctionne pas.

    Si vous avez une solution, merci d'avance

    Cordialement


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    void __fastcall TForm1::Button4Click(TObject *Sender)
    {
     //lister  adresses IP
     for (int i = 0; i< GStack->LocalAddress.RefCount(); i++) //  "Erreur de vérification d'étendue"
      ListBox1->Items->Add(GStack->LocalAddress[i]); // sans la boucle, l'IPV4 s'affiche
    }
     
     
    // le code ci-dessous fonctionne bien
    void __fastcall TForm1::Button3Click(TObject *Sender)
    {
      if (!(GStack->IsIP(Edit1->Text)))
    	ShowMessage ("Erreur");
    	  else  ShowMessage ("Adresse exacte");
     
    }

  2. #2
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Salut
    la méthode LocalAddresses te retourne un TStringList il ffaut donc utiliser la property count
    voici un exemple fonctionnel

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    	String Tmp,IpAddr;
    	 for(int i(0);i<GStack->LocalAddresses->Count;i++)
    	{
    	    IpAddr=GStack->LocalAddresses->Strings[i];
    	   if (GStack->IsIP(IpAddr))
    	  {
    	  Tmp.sprintf(L"%s%d%s%s",L"Carte ",i+1,L" ",IpAddr.c_str());
    	  Memo1->Lines->Add(Tmp); // boucle appellée uniquement si l'adresse Ip est valide ce qui est stupide car retournée par l'OS
    	 }
          }
    résultat obtenu sur ma station de travail
    Nom : CartesRéseaux.PNG
Affichages : 355
Taille : 3,2 Ko
    cdlt
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2014
    Messages
    130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 130
    Points : 59
    Points
    59
    Par défaut
    Salut

    Ça marche merci ... Avec ListBox ou Memo

    Par contre l'adresse IPv6 de liaison locale n'apparaît pas.

    Cordialement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    void __fastcall TForm1::Button4Click(TObject *Sender)
    {
     //Si plusieurs adresses IP
    	 String Tmp,IpAddr;
    	 for(int i(0);i<GStack->LocalAddresses->Count;i++)
     
    	{
    		IpAddr=GStack->LocalAddresses->Strings[i];
    	   if (GStack->IsIP(IpAddr))
    	  {
    	   Tmp.sprintf(L"%s%d%s%s",L"Carte ",i+1,L" ",IpAddr.c_str());
    	   ListBox1->Items->Add(Tmp);
    	   Memo1->Lines->Add(Tmp);
    	 }
    	}
    }

  4. #4
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Il semblerait que ce soit un bug connu
    Regarde ce post https://stackoverflow.com/questions/...-with-ipv6-net

    Cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2014
    Messages
    130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 130
    Points : 59
    Points
    59
    Par défaut
    Je vais voir ça. Merci DJM

    Cordialement

  6. #6
    Membre chevronné
    Avatar de Crayon
    Inscrit en
    Avril 2005
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 811
    Points : 2 189
    Points
    2 189
    Par défaut
    Citation Envoyé par magdani Voir le message
    Par contre l'adresse IPv6 de liaison locale n'apparaît pas.
    Salut, si tu veux lister du IPv6, il ne faut pas vérifier avec la méthode IsIP, car ce code regarde pour du IPv4:
    Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function TIdStack.IsIP(AIP: string): Boolean;
    var
      i: Integer;
    begin
     
     
    //
    //Result := Result and ((i > 0) and (i < 256));
    //
      i := IndyStrToInt(Fetch(AIP, '.'), -1);    {Do not Localize}
      Result := (i > -1) and (i < 256);
      i := IndyStrToInt(Fetch(AIP, '.'), -1);    {Do not Localize}
      Result := Result and ((i > -1) and (i < 256));
      i := IndyStrToInt(Fetch(AIP, '.'), -1);    {Do not Localize}
      Result := Result and ((i > -1) and (i < 256));
      i := IndyStrToInt(Fetch(AIP, '.'), -1);    {Do not Localize}
      Result := Result and ((i > -1) and (i < 256)) and (AIP = '');
    end;
    La doc dit:
    IsIP is a Boolean function used to indicate when the IP address in AIP contains a valid IP address expressed in numeric dotted-decimal form.

    IsIP will return True when the value in AIP contains four byte values (each byte in the range 0 to 255) separated by the '.' delimiter.

    For example:
    • 0.0.0.0 True
    • 255.255.255.255 True
    • 127.0.0.1 True
    • 256.0.0.0 False (The first byte is an invalid value).
    • 127.0.1 False (Not enough values to represent the 32-bit network address).
    • Plus un ordinateur possède de RAM, plus vite il peut générer un message d'erreur. - Dave Barry
    • Je n'ai pas peur des ordinateurs. J'ai peur qu'ils viennent à nous manquer. - Isaac Asimov
    • Le code source est comme une belle femme, plus on le regarde, plus on trouve des défauts. - Crayon

  7. #7
    Membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2014
    Messages
    130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 130
    Points : 59
    Points
    59
    Par défaut
    Merci Crayon.
    Je vais voir ce que cela donne en c++

  8. #8
    Membre chevronné
    Avatar de Crayon
    Inscrit en
    Avril 2005
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 811
    Points : 2 189
    Points
    2 189
    Par défaut
    Citation Envoyé par magdani Voir le message
    Merci Crayon.
    Je vais voir ce que cela donne en c++
    Peut-être que je n'est pas été clair, ce que je veux dire c'est de ne pas utiliser cette condition si tu veux du IPv6:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (GStack->IsIP(IpAddr))
    • Plus un ordinateur possède de RAM, plus vite il peut générer un message d'erreur. - Dave Barry
    • Je n'ai pas peur des ordinateurs. J'ai peur qu'ils viennent à nous manquer. - Isaac Asimov
    • Le code source est comme une belle femme, plus on le regarde, plus on trouve des défauts. - Crayon

  9. #9
    Membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2014
    Messages
    130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 130
    Points : 59
    Points
    59
    Par défaut
    Merci pour ta réponse mais j'ai enlevé cette condition, IPV6 ne s'affiche toujours pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    void __fastcall TForm1::Button4Click(TObject *Sender)
    {
     //Si plusieurs adresses IP
     
    String Tmp,IpAddr; //la méthode LocalAddressese retourne un TStringList il faut donc utiliser la property count
    	 for(int i(0);i<GStack->LocalAddresses->Count;i++)
     
    	{
    	   IpAddr=GStack->LocalAddresses->Strings[i];
    	   Tmp.sprintf(L"%s%d%s%s",L"Carte ",i+1,L" ",IpAddr.c_str());
    	   ListBox1->Items->Add(Tmp);
    	}
    }

  10. #10
    Membre chevronné
    Avatar de Crayon
    Inscrit en
    Avril 2005
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 811
    Points : 2 189
    Points
    2 189
    Par défaut
    Il ne faut pas utiliser LocalAddresses c'est deprecated, il faut prendre GetLocalAddresses:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        property LocalAddresses: TStrings read GetLocalAddresses; // {$IFDEF HAS_DEPRECATED}deprecated{$IFDEF HAS_DEPRECATED_MSG} 'use GetLocalAddressList()'{$ENDIF};{$ENDIF}
    Voici le code que j’utiliserai (j'ai testé dans un projet FireMonkey et ça fonctionne bien):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    28
    29
    30
    31
        ListBox1->BeginUpdate();
        ListBox1->Items->Clear();
        TIdStackLocalAddressList* LLocalAddresses = NULL;
        try
        {
            LLocalAddresses = new TIdStackLocalAddressList();
            TIdStack::IncUsage(); // Ensures GStack is available even if no Indy components are active
            GStack->GetLocalAddressList(LLocalAddresses);
            TIdStack::DecUsage();
     
            const int LIpCount = LLocalAddresses->Count;
            for(int i = 0; i < LIpCount; ++i)
            {
                String Tmp;
                TIdStackLocalAddress* LStackLocalAddress = LLocalAddresses->Addresses[i];
                if(LStackLocalAddress->IPVersion == TIdIPVersion::Id_IPv4)
                {
                    Tmp = String().sprintf(L"Carte IPv4 %d %s", i + 1, LStackLocalAddress->IPAddress.c_str());
                }
                else if(LStackLocalAddress->IPVersion == TIdIPVersion::Id_IPv6)
                {
                    Tmp = String().sprintf(L"Carte IPv6 %d %s", i + 1, LStackLocalAddress->IPAddress.c_str());
                }
                ListBox1->Items->Add(Tmp);
            }
        }
        __finally
        {
            delete LLocalAddresses;
        }
        ListBox1->EndUpdate();
    • Plus un ordinateur possède de RAM, plus vite il peut générer un message d'erreur. - Dave Barry
    • Je n'ai pas peur des ordinateurs. J'ai peur qu'ils viennent à nous manquer. - Isaac Asimov
    • Le code source est comme une belle femme, plus on le regarde, plus on trouve des défauts. - Crayon

  11. #11
    Membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2014
    Messages
    130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 130
    Points : 59
    Points
    59
    Par défaut
    Super. Merci Crayon.

    Bien cordialement

  12. #12
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    bonjour
    merci à Crayon pour le code
    Sous VCL le composant LIstBox , la méthode BeginUpdate().et EndUpdate() fait partie de la propriété Items
    je me suis permis d'apporter certaines modifications au code de Crayon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    void __fastcall TForm129::Button2Click(TObject *Sender)
    {
     
    	ListBox1->Items->BeginUpdate();
    	ListBox1->Items->Clear();
    	String Tmp;
    	try
    	{
    	   auto LLocalAddresses = new TIdStackLocalAddressList();    // l'usage de Auto nous dispense de la destruction de l'object
    		//TIdStack::IncUsage(); // Ensures GStack is available even if no Indy components are active
    		// Ce programme ne pourra compilé si aucun composant Indy n'est déposé sur la Form Principale
    		// la méthode m'apporte riem  par ailleurs les méthodes
    		// IncUsage et DecUsage ne doive pas être appelée directement (voir aide Indy)
    		GStack->GetLocalAddressList(LLocalAddresses);
    		//TIdStack::DecUsage();
     
    	   //	const int LIpCount = LLocalAddresses->Count;
    		for(int i(0); i < LLocalAddresses->Count; i++)
    		{
    			TIdStackLocalAddress* LStackLocalAddress = LLocalAddresses->Addresses[i];
     
    			if(LStackLocalAddress->IPVersion == TIdIPVersion::Id_IPv4)
    			{
    				Tmp = String().sprintf(L"Carte IPv4 %d %s", i + 1, LStackLocalAddress->IPAddress.c_str());
    			}
    			else if(LStackLocalAddress->IPVersion == TIdIPVersion::Id_IPv6)
    			{
    				Tmp = String().sprintf(L"Carte IPv6 %d %s", i + 1, LStackLocalAddress->IPAddress.c_str());
    			}
    			ListBox1->Items->Add(Tmp);
    		}
    	}
    	catch(Exception &E)
    	{
    	   ShowMessage(E.Message);    // peut être supprimé dans un code fonctionnel
    	}
    	ListBox1->Items->EndUpdate();
    }
    //---------------------------------------------------------------------------
    code testé sous VCL et FMX

    bien cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  13. #13
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    bonjour
    merci à Crayon pour le code
    Sous VCL le composant LIstBox , la méthode BeginUpdate().et EndUpdate() fait partie de la propriété Items
    je me suis permis d'apporter certaines modifications au code de Crayon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    void __fastcall TForm129::Button2Click(TObject *Sender)
    {
     
    	ListBox1->Items->BeginUpdate();
    	ListBox1->Items->Clear();
    	String Tmp;
    	try
    	{
    	   auto LLocalAddresses = new TIdStackLocalAddressList();    // l'usage de Auto nous dispense de la destruction de l'object
    		//TIdStack::IncUsage(); // Ensures GStack is available even if no Indy components are active
    		// Ce programme ne pourra compilé si aucun composant Indy n'est déposé sur la Form Principale
    		// la méthode m'apporte riem  par ailleurs les méthodes
    		// IncUsage et DecUsage ne doive pas être appelée directement (voir aide Indy)
    		GStack->GetLocalAddressList(LLocalAddresses);
    		//TIdStack::DecUsage();
     
    	   //	const int LIpCount = LLocalAddresses->Count;
    		for(int i(0); i < LLocalAddresses->Count; i++)
    		{
    			TIdStackLocalAddress* LStackLocalAddress = LLocalAddresses->Addresses[i];
     
    			if(LStackLocalAddress->IPVersion == TIdIPVersion::Id_IPv4)
    			{
    				Tmp = String().sprintf(L"Carte IPv4 %d %s", i + 1, LStackLocalAddress->IPAddress.c_str());
    			}
    			else if(LStackLocalAddress->IPVersion == TIdIPVersion::Id_IPv6)
    			{
    				Tmp = String().sprintf(L"Carte IPv6 %d %s", i + 1, LStackLocalAddress->IPAddress.c_str());
    			}
    			ListBox1->Items->Add(Tmp);
    		}
    	}
    	catch(Exception &E)
    	{
    	   ShowMessage(E.Message);    // peut être supprimé dans un code fonctionnel
    	}
    	ListBox1->Items->EndUpdate();
    }
    //---------------------------------------------------------------------------
    code testé sous VCL et FMX

    petite remarque selon la configuration réseau de Windows 1 carte réseau peut avoir à la fois une adresse en IPV4 et en IPV6
    le nombre d'éléments retournés sera par conséquent faux

    bien cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  14. #14
    Membre chevronné
    Avatar de Crayon
    Inscrit en
    Avril 2005
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 811
    Points : 2 189
    Points
    2 189
    Par défaut
    @DjmSoftware, je suis en désaccord avec la plupart de tes changements. Laisse moi t'expliquer pourquoi.

    1) Tu as changer le scope de la variable Tmp pour l'élargir. Ceci est une mauvaise pratique. Il faut toujours avoir le scope le plus petit. Un outil comme cppcheck va normalement te mettre un avertissement la dessus. Sinon, pas plus tard que cette semaine je lisais le livre Code Complete qui stipulait la même chose.

    2) Cette information est fausse:
    Citation Envoyé par DjmSoftware Voir le message
    bonjour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    		// Ce programme ne pourra compilé si aucun composant Indy n'est déposé sur la Form Principale
    		// la méthode m'apporte riem  par ailleurs les méthodes
    		// IncUsage et DecUsage ne doive pas être appelée directement (voir aide Indy)
    Si tu fais un nouveau projet VCL et que tu mets ton code dans le constructeur et que tu ajoutes cette ligne le code devrait fonctionné:
    Si tu ne met pas les IncUsage() / DecUsage() tu vas obtenir un Access Violation.
    Si tu les mets, le programme va fonctionner sans nécessiter l'ajout de composant Indy.
    La documentation dit:
    Please note that applications do not normally call the IncUsage and DecUsage methods for the global stack instance
    Il y a le mot normally, ici je juge que c'est un usage non-normal

    3) Cette affirmation est aussi fausse:
    Citation Envoyé par DjmSoftware Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    	   auto LLocalAddresses = new TIdStackLocalAddressList();    // l'usage de Auto nous dispense de la destruction de l'object
    Ton code va générer une fuite de mémoire. Ce que tu dit sur auto est erroné. Je crois que tu te mélanges avec auto_ptr.
    Le destructeur ne sera jamais appelé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    destructor TCollection.Destroy;
    Tu peux y mettre un break point et vérifié si tu ne me crois pas
    En plus, auto ne fonctionne pas avec bcc32, qui est selon moi le seul compilateur qui fonctionne correctement.

    5) Ici c'est une question de bonne pratique, tu as changer mon ++i en i++. Pour un entier cela n'a pas d'importance, mais étant donné que ça en a pour d'autre type, la bonne pratique c'est de toujours mettre ++i dans un contexte de boucle.
    Citation Envoyé par DjmSoftware Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    		for(int i(0); i < LLocalAddresses->Count; i++)
    Tu peux faire une recherches sur Internet pour voir ce que les autres en penses, tu devrais voir que je ne suis pas le seul.

    4) Pour mon dernier point, je ne suis pas certain. Je n'est jamais vérifié si C++Builder optimisait les propriétés.
    Si ce n'est pas le cas, à chaque fois que Count est invoqué dans la boucle:
    Citation Envoyé par DjmSoftware Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	   //	const int LIpCount = LLocalAddresses->Count;
    		for(int i(0); i < LLocalAddresses->Count; i++)
    Le code va appeler ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function TCollection.GetCount: Integer;
    begin
      Result := FItems.Count;
    end;
    On s’entend que c'est juste un pointeur vers la méthode GetCount, mais c'est pourquoi j'utilise une variable temporaire. Mais je ne suis pas certain, il faudrait vérifier le code asm généré en Release pour être certain et je n'est pas le temps maintenant


    J'espère que je me suis justifié d'une manière approprié. J'ai tenté de parler de bonne pratique et non de préférences personelles. Vois ça comme un code review
    • Plus un ordinateur possède de RAM, plus vite il peut générer un message d'erreur. - Dave Barry
    • Je n'ai pas peur des ordinateurs. J'ai peur qu'ils viennent à nous manquer. - Isaac Asimov
    • Le code source est comme une belle femme, plus on le regarde, plus on trouve des défauts. - Crayon

  15. #15
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    bonsoir Crayon
    tes remarques sont pertinentes mais je ne suis pas en d'accord avec certaines d'elles et je ne suis en aucune manière affecté par tes excellents commentaires.

    d'une manière générale Indy c'est du delphi code similaire ci-dessous

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    var
      LList: TIdStackLocalAddressList;
      LAddr: TIdStackLocalAddress;
      I: Integer;
    begin
      LList := TIdStackLocalAddressList.Create;
      try
        GStack.GetLocalAddressList(LList);
        for I := 0 to LList.Count-1 do begin
          LAddr := LList[I];
          case LAddr.IPVersion of
            Id_IPv4: begin
              // use LAddr.IPAddress as needed...
              // use TIdStackLocalAddressIPv4(LAddr).SubNetMask as well...
            end;
            Id_IPv6: begin
              // use LAddr.IPAddress as needed...
            end;
          end;
        end;
      finally
        LList.Free;
      end;
    end;
    je ne vois pas d'utilisation de IdStack::IncUsage(); et IdStack:ecUsage()
    cela étant je ne me suis pas penché sérieusement sur la question




    Si tu fais un nouveau projet VCL et que tu mets ton code dans le constructeur et que tu ajoutes cette ligne le code devrait fonctionné:

    #include <IdStack.hpp>
    dans le cas exposé par Magdani un composant Indy etait déposé sur a Form Principale ce que j'ai également fait dans mon programme

    par ailleurs je ne suis pas certain que le fait d'inclure ce fichier soit suffisant pour initialiser correctement la GStacK.


    3) Cette affirmation est aussi fausse


    auto LLocalAddresses = new TIdStackLocalAddressList(); // l'usage de Auto nous dispense de la destruction de l'object

    Ton code va générer une fuite de mémoire. Ce que tu dit sur auto est erroné. Je crois que tu te mélanges avec auto_ptr.
    Le destructeur ne sera jamais appelé:

    pas d'accord:
    jette un coup d'oeil sur la documentation http://docwiki.embarcadero.com/RADStudio/Sydney/en/Auto

    Auto_ptr fait partie de la STL et nécessite le fichier d'entete <memory>

    quand au compilateur BCC32 n'est plus maintenu. par défaut c'est la nouvelle version BCC32C compatible CLANG (mis a niveau partiellement avec avec les nouvelles évolutions du C++ )qui doit être utilisée dixit Embarcaero.



    4) Pour mon dernier point, je ne suis pas certain. Je n'est jamais vérifié si C++Builder optimisait les propriétés.
    Si ce n'est pas le cas, à chaque fois que Count


    // const int LIpCount = LLocalAddresses->Count;
    for(int i(0); i < LLocalAddresses->Count; i++)
    pas d'accord ici non plus toutes les propriétés initialisés qui utilisent la méthode Get sont en lecture seule et par conséquent non modifiables
    par ailleurs l’optimisation ne changera pas la valeur du champ FCount qui a initialisé préalablement par un Setter

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for(int i(0); i < LLocalAddresses->Count; i++)
     
    // dans cette boucle la propriété est lue et ne change pas tout au long du code.
    quand au fait d'utiliser la pré --i ou post ++I cela dépend totalement de l'utilisation. dans la littérature française c’est plutôt le pré alors que les Anglophones utilisent généralement la post.

    cela étant je te remercie pour le temps passé à la revue de mes corrections.

    un désaccord apporte au minimum inintéressantes discussions.


    bien cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  16. #16
    Membre chevronné
    Avatar de Crayon
    Inscrit en
    Avril 2005
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 811
    Points : 2 189
    Points
    2 189
    Par défaut
    DjmSoftware, l'utilisation de IncUsage() / DecUsage() est suffisant pour utiliser GStacK. Aucun composant Indy supplémentaire n'est nécessaire. Par contre, tu as raison que si Magdani utilise un composant TIdTCPServer sur sa TForm, il n'a pas besoin d’appeler ces deux fonctions car TIdTCPServer descend de TIdComponent et dans son "constructeur" on retrouve IncUsage:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TIdComponent.InitComponent;
    begin
      inherited InitComponent;
      TIdStack.IncUsage;
    end;
    C'est juste que dans mon code je préfère toujours les appeler car je ne connais pas toujours le contexte d'utilisation.

    Pour auto, je maintiens mon point. Je connais bien son utilisation et il ne sert pas de smart pointer. Fais ce test rapide, ajoute cette classe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class TTest : public TObject
    {
    private:
        String FName;
    protected:
        int __fastcall GetCount()
        {
            Sleep(5000); // ici on pourrait avoir n'importe quoi
            return 10;
        }
    public:
        __fastcall TTest(const String &AName = "pas de nom") : TObject(), FName(AName)
        {
            ShowMessage("Construction de " + FName);
        }
        __fastcall virtual ~TTest()
        {
            ShowMessage("Destruction de " + FName + "!!!");
        }
     
        __property String Name = {read=FName}; // lecture seul
        __property int Count = {read=GetCount}; // lecture seul
    };
    Par suite, utilise ce code pour regarder si j'ai raison
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        TTest* LTest1 = new TTest("Test1");
        delete LTest1;
     
        auto LTest2 = new TTest("Test2");
     
        std::auto_ptr<TTest> LTest3(new TTest("Test3"));
    Tu vas voir que pour Test2, le destructeur n'est jamais appelé.

    Je sais que bcc32 date des années 90 C'est juste qu'avec les compilateurs CLANG, il y a plein choses qui ne fonctionnent pas. Pour citer qu'un seul exemple : l'auto complete. C'est le cas du moins avec la version C++Builder 10.3. C'est pour cette raison que je continu d'utiliser le vieux compilateur en développement.

    Pour la propriété Count, je suis d'accord que la valeur est read only et que l'optimisation ne va pas la changée. Par contre, avec la même classe de TTest. Essaie ces deux codes:
    1) On met le nombre dans une variable temporaire que l'on utilise par la suite dans la boucle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        int LCount = LTest3->Count;
        for(int i = 0; i < LCount; ++i) {}
    2) On utilise directement la propriété Count (comme tu le suggères):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        for(int i = 0; i < LTest3->Count; ++i) {}
    Tu vas trouvé que dans le deuxième cas tu attends pas mal plus longtemps. 5 secondes vs 50 secondes. Pourtant comme tu dis:
    Citation Envoyé par DjmSoftware Voir le message
    pas d'accord ici non plus toutes les propriétés initialisés qui utilisent la méthode Get sont en lecture seule et par conséquent non modifiables
    par ailleurs l’optimisation ne changera pas la valeur du champ FCount qui a initialisé préalablement par un Setter

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(int i(0); i < LLocalAddresses->Count; i++)
     
    // dans cette boucle la propriété est lue et ne change pas tout au long du code.
    La valeur ne change pas, mais par contre le comportement est différent.
    J'espère que cet exemple te feras comprendre pourquoi je me méfie d'appeler une propriété dans un boucle.
    • Plus un ordinateur possède de RAM, plus vite il peut générer un message d'erreur. - Dave Barry
    • Je n'ai pas peur des ordinateurs. J'ai peur qu'ils viennent à nous manquer. - Isaac Asimov
    • Le code source est comme une belle femme, plus on le regarde, plus on trouve des défauts. - Crayon

  17. #17
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Salut Crayon,
    Je suis un ancien développer Delphi et j’ai migré sur c++ builder dès sa version initiale c++ builder 1
    Tu a certainement pu remarquer qu’Embarcadero ne faisait plus guère progresser c++. Builder si ce n’est que dans des prix délirants. ( plus de modélisation depuis 10 ans, un intellisight désastreux en comparaison de Delphi,Support Android et Apple limité à 32 bits ce qui rend le code inutilisable… ) et je m’arrête la..

    Je suis d’accord avec les remarques suivantes:
    1. IncUsage() / DecUsage() : merci de m’avoir fair connaître ces 2 méthodes que j’ignorais.

    2. Les smarts pointeurs de la STL je peux t’assurer que la destruction se fait correctement. Pour s’en convaincre il faut utiliser des outils spécifiques de recherche des leaks

    3. Mot clé auto qui a des comportements différences en fonction de la version c++ (11,17,20) j’aurais du utiliser un des smart pointeurs de la STL. Merci pour l’info.

    4. Propriété dans une boucle petit rappel Indy c’est du Delphi pur et je n’ai fait que porter le code existant (posté) en c++.
    Par contre en c++ pur je suis parfaitement d’accord avec toi bien que je déteste utiliser des objets temporaires à l’extérieur d’une classe.

    Bien cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  18. #18
    Membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2014
    Messages
    130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 130
    Points : 59
    Points
    59
    Par défaut Appeler une page web
    Bonjour,

    Dans la continuité des connexions, je cherche un moyen d'ouvrir une page web.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ShellExecute (Handle,"open","http://www.developpez.com",NULL,NULL,SW_NORMAL);
    Le code ci-dessus donne les erreurs suivantes :
    [bcc32 Erreur] Unit1.cpp(130): E2034 Impossible de convertir 'TWindowHandle * const' en 'HWND__ *'
    [bcc32 Erreur] Unit1.cpp(130): E2342 Mauvaise correspondance de type dans le paramètre 'hwnd' ('HWND__ *' désiré, 'TWindowHandle *' obtenu)
    J'ai bidouillé le code ci-dessous d'après un code Delphi, mes connaissances étant assez limitées en la matière, ça plante ...

    Cordialement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    String recup(String getrecup, TStream *DestStream)
    {
      DestStream = new TStream();
     
      return getrecup;
     
    }
     
    void __fastcall TForm1::DownloadHTTP(const String AUrl, TStream *DestStream)
    {
     
     if (serveur->Active == true) recup(AUrl,DestStream);
     
    }
     
     
    void __fastcall TForm1::Button5Click(TObject *Sender)
    {
      TFileStream *Fs = new TFileStream("temp.txt", fmCreate);
      DownloadHTTP("http://www.developpez.com",new TStream(Fs)); // [bcc32 Erreur] Unit1.cpp(122): E2285 Impossible de trouver une correspondance pour 'TStream::TStream(TFileStream *)'
      delete Fs;
    }

  19. #19
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Salut

    le .h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #ifndef Project2H
    #define Project2H
    #include <IdBaseComponent.hpp>
    #include <IdComponent.hpp>
    #include <IdHTTP.hpp>
    #include <IdIOHandler.hpp>
    #include <IdIOHandlerSocket.hpp>
    #include <IdIOHandlerStack.hpp>
    #include <IdSSL.hpp>
    #include <IdSSLOpenSSL.hpp>
    #include <IdTCPClient.hpp>
    #include <IdTCPConnection.hpp>
    #include <System.Classes.hpp>
    #include <Vcl.Controls.hpp>
    #include <Vcl.StdCtrls.hpp>
     
    //---------------------------------------------------------------------------
     
    //---------------------------------------------------------------------------
    class TForm130 : public TForm
    {
    __published:	// Composants gérés par l'EDI
    	TButton *Button1;
    	TMemo *Memo1;
    	void __fastcall Button1Click(TObject *Sender);
     
     
    private:	// Déclarations utilisateur
    public:		// Déclarations utilisateur
    	__fastcall TForm130(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm130 *Form130;
    //---------------------------------------------------------------------------
    #endif
    et finalement le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    28
    29
     
    void __fastcall TForm130::Button1Click(TObject *Sender) {
     
    	String FileName(L"test.txt");
    	TIdHTTP *Http2 = new TIdHTTP(NULL);
    	TIdSSLIOHandlerSocketOpenSSL* SSLHandler =
    		new TIdSSLIOHandlerSocketOpenSSL(NULL);
    	TFileStream *fs = new TFileStream(FileName, fmCreate);
    	SSLHandler->SSLOptions->SSLVersions << sslvTLSv1 << sslvTLSv1_1 <<
    		sslvTLSv1_2;
    	Http2->IOHandler = SSLHandler;
    	try {
    		try {
    			Http2->Get("https://www.developpez.com", fs);
     
    		}
    		catch (Exception&E) {
    			ShowMessage(E.Message);
    		}
    	}
    	__finally {
    		delete fs;
    		delete SSLHandler;
    		delete Http2;
            Memo1->Clear();
    		Memo1->Lines->LoadFromFile(FileName);
     
    	}
    }
    cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  20. #20
    Membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2014
    Messages
    130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 130
    Points : 59
    Points
    59
    Par défaut
    Je vais étudier ton code
    Merci DJM
    Cordialement

Discussions similaires

  1. Comment lister les adresses emails d'un fichier
    Par djibril dans le forum Téléchargez
    Réponses: 0
    Dernier message: 30/06/2011, 15h28
  2. Réponses: 2
    Dernier message: 24/09/2010, 10h34
  3. lister les adresses ip
    Par flolebreton dans le forum Langage
    Réponses: 19
    Dernier message: 14/12/2009, 16h21
  4. Lister les adresses IP
    Par soft0613 dans le forum Entrée/Sortie
    Réponses: 8
    Dernier message: 23/03/2008, 21h15
  5. Cherche à lister les adresses IP dispo sur la machine
    Par yukkyyuk dans le forum Windows
    Réponses: 3
    Dernier message: 16/03/2005, 11h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo