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

Web & réseau Delphi Discussion :

[Delphi 7] Utilisation des composants Indy TCPServer et TCPClient


Sujet :

Web & réseau Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    174
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 174
    Par défaut [Delphi 7] Utilisation des composants Indy TCPServer et TCPClient
    Bonjour,

    J'ai codé une 2 petites applications Delphi 7 de test pour apprendre à bien utiliser les composant Indy TIdTCPServer et TIdTCPClient.
    Les 2 applications sont très simples et fonctionnent à peu près. Comme vous vous en doutez, c'est le "à peu près" qui me gêne.

    En fait je pense ne pas avoir bien compris certains concepts de ces composants, notamment la propriété Bindings du composant TIdTCPServer.

    Le problème que je rencontre avec mes 2 executables est le suivant : je lance le serveur, puis je lance le client. Quand je clique sur le bouton "Connect" de mon client, tout se passe bien.
    Par contre, si je clique sur le bouton "Disconnect" du client puis qu'ensuite je clique sur le bouton "Connect", j'ai une exception qui se déclenche : "Address already in use".

    Je ne comprends pas du tout ce qui se passe.

    J'ai mis en pièce jointe le code des 2 applications.

    Si quelqu'un peut y jeter un oeil...

    Merci d'avance.
    Fichiers attachés Fichiers attachés

  2. #2
    Expert éminent
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    en IP v4, un serveur est identifié par un @IP et un numéro de port (le binding), sur une même machine je peux avoir différents serveurs sur différents ports

    quand on tente de faire un binding sur un port déjà utilisé on a l'erreur "Address already in use"

    je suis surpris que tu puisses avoir cette erreur au niveau client, car généralement on ne définie pas de Binding au niveau client; un numéro de port aléatoire est attribué automatique (car on a toujours un numéro de port, y compris pour le client, car lui aussi peut faire plusieurs connexions en même temps depuis la même adresse, c'est le port qui va permettre de savoir qui fait la requête)
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 982
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 982
    Par défaut
    Je n'ai pas regardé le Zip, Indy 9 par défaut de Delphi 7 ?
    Je n'ai pas du tout aimé ces composants à l'époque

    Un test simple, un telnet, comme se comporte-t-il lorsqu'il se connecte sur le serveur ?

    Pour Bindings, en local, avec le TIdFTPServer (hérite du TIdTCPServer), je me souviens que ça ralait, j'ignore si c'est valable.
    C'était uniquement en localhost que ça provoquait une erreur côté client de ce type lorsque j'avais un client Delphi + FileZilla dessus

    EDIT, je confirme, le dernier TIdTCPServer que j'ai codé pour que ça déconne pas en local, j'ai ajouté ça

    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
    procedure TEtiquetteServeur.InitServeurTCP();
    begin
      WebServerTCP.Bindings.Clear();
      with WebServerTCP.Bindings.Add() do 
      begin
        IP := '0.0.0.0';
        Port := GUEST_CLIENT_PORT_TCP;
      end;
      WebServerTCP.OnExecute := WebServerTCPExecute;
      WebServerTCP.Active := True;
    end;
     
    procedure TEtiquetteServeur.InitServeurHTTP;
    begin
      {  TIdHTTPServer.KeepAlive
       propriété), mais ce n’est toujours pas une garantie. Le client, ou un proxy / routeur
       entre le client et le serveur, peut toujours fermer la connexion à tout moment.  }
      //WebServerHTTP.KeepAlive := True;
      WebServerHTTP.OnCommandGet := FIdHTTPServerCommandGet;
      WebServerHTTP.OnConnect  := CustomOnConnect;
      WebServerHTTP.MaxConnections := 20;
      with WebServerHTTP.Bindings.Add() do 
      begin
        IP := '0.0.0.0';
        Port := GUEST_CLIENT_PORT_HTTP;
      end;
      WebServerHTTP.Active := True;
    end;
    WebServerTCP et WebServerHTTP sont créés dynamiquement dans un Service Windows, pas de TForm.
    C'est une sorte de routeur, des programmes abonnés TCP attendent des ordres et d'autres programmes envoient des ordres en HTTP, le serveur lui va router les ordres vers l'abonné cible et cela entre la France, la Chine, l'Inde ... un jour faudrait que je demande comment ça tient les milliers d'ordre journalier, une collègue et moi avions développé cela peut de temps avant de partir ...

    Note donc qu'il y a bien deux serveurs sur deux ports différents sans problème
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    174
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 174
    Par défaut
    Je pense avoir résolu mes problèmes.
    En fait, j'ai simplifié pas mal les choses : je n'utilise plus la propriété "Binding" sur le composant TIdTCPServer et côté TIdTCPClient, je n'utilise plus non plus les propriétés "BoundIP" et "BoundPort".

    Je joins la nouvelle version de mon code pour ceux que ça intéresse.
    Fichiers attachés Fichiers attachés

  5. #5
    Membre actif

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2012
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2012
    Messages : 58
    Billets dans le blog
    1
    Par défaut
    N'hesitez pas à clore la discussion, si vôtre problème a été résolu !!! Cordialement !!

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    174
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 174
    Par défaut
    Bonjour à tous,

    En fait, j'ai encore quelques soucis avec les composants Indy.
    Je ne sais pas trop comment arrêter proprement mon serveur TCP.

    J'ai ajouté le code suivant sur l'evenement "OnClick" du bouton "Stop serveur" :

    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
     
     
    {-------------------------------------------------------------------
      Gestion du click sur le bouton "Stop Serveur"
    -------------------------------------------------------------------}
    procedure TServer_Form.Stop_Server_ButtonClick(Sender: TObject);
    begin
      if not TCP_Server.Active then Exit;
      try
        TCP_Server.Active := False;
      except
        On E:Exception do
          Begin
           ListBox2.Items.Add('Arret du serveur, Error : ' +  E.Message);
          End;
      end;
    end;
    Mais quand j'ai des clients connectés sur le serveur, j'ai l'exception "Terminate Thread timeout" qui se déclenche.
    Du coup, je ne sais pas trop comment stopper proprement mon serveur.
    Faut-il au préalable que je boucle sur tous les threads clients et que je les deconnecte?

    D'ailleurs l'autre question que je me pose, c'est comment fermer proprement mon application quand j'ai encore des connexions actives sur mon serveur ?

  7. #7
    Expert éminent
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Par défaut
    1) alors couper la connexion du serveur implique qu'il n'est plus à l'écoute du port sélectionné...mais tous les clients connectés sont actuellement sur un autre port, et stopper le serveur n'implique pas de couper les clients actifs (en fait je ne sais pas si TidTCPServer le fait ou pas)

    2) quand l'application se ferme, tous les sockets sont fermés, donc à part se préoccuper de faire les choses "proprement" ça n'a pas bcp d'importance

    ensuite, vu que tu sembles utiliser ton propre protocole de communication, tu peux très bien envoyer un ordre de déconnexion à tous tes clients quand tu veux fermer le serveur, ça permet à la partie client de gérer une coupure du serveur propre sans se demander pourquoi il n'est plus connecté.

    sur un serveur RESTfull je me contente de sauvegarde les identifiants de sessions actives avant fermeture, et je les relit au lancement, ce qui me permet de mettre à jour l'appli serveur sans perturber les sessions Web, c'est assez cool en fait et comme c'est du RESTfull je n'ai pas de connexion permanente (sauf des WebSocket mais c'est autrechose encore), les clients ne voient même pas l'interruption de service
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

Discussions similaires

  1. [Lazarus] Installation et utilisation des composants Indy sous Ubuntu
    Par tuxy dans le forum Lazarus
    Réponses: 13
    Dernier message: 03/06/2015, 14h14
  2. Réponses: 2
    Dernier message: 10/03/2014, 11h56
  3. Réponses: 0
    Dernier message: 03/04/2013, 11h33
  4. Utilisation des composants Indy
    Par pduceux dans le forum Delphi
    Réponses: 1
    Dernier message: 11/05/2007, 20h45
  5. Compilation des composants Indy 10
    Par rconty dans le forum C++Builder
    Réponses: 23
    Dernier message: 13/07/2005, 15h48

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