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 :

Problème sur SocketHandle conflit d'identifiant


Sujet :

Web & réseau Delphi

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Février 2010
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 533
    Points : 124
    Points
    124
    Par défaut Problème sur SocketHandle conflit d'identifiant
    Bonjour,

    Suite à de précieux conseils en rapport à cette discussion
    J'utilise le Sockethandle pour gérer les identifiants d'un parc de scans. Un scan envoit une requête mon serveur lui renvoie la réponse. Et pour savoir à quel scan renvoyer la réponse j'utilise mon sockethandle :

    Quand mon scan envoit une demande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          idConnect := Socket.SocketHandle;
    Je stocker cet identifiant dans le champ idconnexion de ma table AdresseIp et quand je renvoi mon information :

    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 envoiMsgSocket(IdScan : Integer; sCodeBarre : String; sMessage : String;ServerSocket : TServerSocket; Trace : TMemo);
    var
      iTailleMessage : Integer;
      idDeConnexion : integer;
      FichierIni : TIniFile;
      ActiveTrace : integer;
    begin
    //Je calcule la taille du message qu'on va envoyer.
    //Pourquoi ? Parce que sous WinDev on utilise le mode de transmission SocketTailleDébut et le mode de transmission doit être
    //identique sur le poste serveur et sur le poste client il faut donc préciser la taille du message et le message !!
    try
       FichierIni := TIniFile.Create(PathExe + 'paramSkipradio.ini');
       ActiveTrace := StrToInt(FichierIni.ReadString('ActiveTrace', 'Active', 'Erreur'));
    
       idDeConnexion := IndexHandle(ServerSocket, IdScan);
       iTailleMessage := Length(sMessage);
       ServerSocket.Socket.Connections[idDeConnexion].SendText(IntToStr(iTailleMessage) +CRLF+ sMessage);
       maDate := FormatDateTime('dd/mm/yyyy hh:nn:ss', Now);
       Trace.Lines.Add(maDate + ' Réponse envoyée au client ' + IntToStr(idScan) + ' ' + sMessage);
       if ActiveTrace = 1 then
       begin
        WriteTrace(maDate + ' :' + ' TailleMessage : ' + IntToStr(iTailleMessage) + ' Message envoyé : ' + sMessage);
       end;
       FichierIni.Free;
       except
        on E : Exception do LogErreur('Anomalie dans l''envoi du message vers le programme radio - Main - envoiMsgSocket ' + ' Message d''erreur : '+ e.Message);
    end;
    end;
    Je renvoi grâce à ma socket et l'id de connexion du scan.

    Cependant après tests je m'aperçois que certains scans récupère parfois le même identifiant ce qui génère de sacrés conflits...

    Est ce que quelqu'un pourrait m'aider ?
    Windows XP
    Delphi 7

    WinDev Mobile 17

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 501
    Points : 24 988
    Points
    24 988
    Par défaut
    Citation Envoyé par juju1988 Voir le message
    Je stocker cet identifiant dans le champ idconnexion de ma table AdresseIp
    Tu ne devrais pas le stocker dans une table ou tableau
    Tu devrais créer pour chaque requête une structure qui contient SocketHandle et les données !
    Avec un Pointer, tu peux gérer des format de message différent !

    Car si tu as plusieurs clients sur la même IP mais via plusieurs instances du programme ou plusieurs ports, tu risque d'écraser et de mélanger les handle entre deux messages


    Donc cette structure de requête, tu la passe de fonction en fonction jusqu'à l'envoie, d'ailleurs, la réponse pourrait être contenu dans cette structure, tient voici la structure qui correspond au à la version originale du code que tu as cité :

    Citation Envoyé par ShaiLeTroll Voir le message
    Ce code est un peu vieux (2001)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ...
                  Index := IndexHandle(FrmMainServeur.SocketDFT, TTelegrammeDFT(TelegrammeDFTLst[I]^).Handle) ;
                  FrmMainServeur.SocketDFT.Socket.Connections[Index].SendText(TTelegrammeDFT(TelegrammeDFTLst[I]^).Acquittement);
    ....
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    function IndexHandle (var ServerSocket : TServerSocket; Handle : Integer) : Integer ;
    var
        I : integer;
    begin
        // Verification de la connexion
        Result := -1 ;
        for I := ServerSocket.Socket.ActiveConnections - 1 downto 0 do begin
            if (Handle) = ServerSocket.Socket.Connections[i].SocketHandle then begin
                Result := I ;
                Break ;
            end;
        end;
    end ;
    Note que le Handle est considéré comme faisait parti de la Donnée, pour chaque CodeBarre reçu on conserve le Handle qui en a été l'origine

    TelegrammeDFTLst est une liste alimentée par le OnRead du Socket
    Handle a reçu le SocketHandle à ce moment là !


    Dans mon programme, il y avait plusieurs clients mais l'un d'entre eux lui se connectait plusieurs fois et sur plusieurs ports !
    Il fallait donc conserver pour chaque message le handle !


    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    // déclaration des strucutres de Télégrammes DFT
    // Entete d’un Télégramme DFT
    type THeaderTelegrammeDFT = record
         LancementTele: String[2];
         TypeTele: String[2];
         VersionTele: String[2];
         ExpediteurTele: String[3];
         DestinataireTele: String[3];
         TempsTele: String[18];
         CompteurTele: String[5];
         LongueurTele: String[4];
    end;
     
    type TAckDFT = record
         EnteteAck: THeaderTelegrammeDFT ;
         EnteteData: THeaderTelegrammeDFT ;
         Data: Pointer ; // Pointeur sur un TTelegrammeTx
         Code: Word ;
    end;
     
    type TReponseDFT = record
         Entete: THeaderTelegrammeDFT ;
         Data: Pointer ; // Pointeur sur un TTelegrammeTx
    end;
     
    // Structure complète d’un Télégramme DFT
    type TTelegrammeDFT = record
         Entete: THeaderTelegrammeDFT ;
         Data: Pointer ; // Pointeur sur un TTelegrammeTx
         TimeToSend: TDateTime;
         Handle : Integer ; // LUI C'EST LE FAMEUX Socket.SocketHandle
         Traite: Boolean ;
         Acquitte: Boolean ;
         Envoie: Boolean ;
         Acquittement: TAckDFT ; 
         Reponse: TReponseDFT ;
    end;
     
    type TTelegrammeT1 = record
         TypeChargement: String[3];
         UniqueP: String[6];
         CodeBarre: String[13];
         Etat: String[3];
    end;
     
    type TTelegrammeT2 = record
         NoBarre: String[5];
         UniqueP: String[6];
         CodeBarre: String[13];
         Etat: String[3];
    end;
     
    type TTelegrammeT3 = record
         TypeChargement: String[3];
         UniqueP: String[6];
         CodeBarre: String[13];
         Etat: String[3];
         NoBarre: String[5];
    end;
     
    type TTelegrammeT4 = record
         TypeChargementAllee: String[3];
         EtatAllee: String[2];
         TypeChargementSortie: String[3];
         EtatSortie: String[2];
         FlagsAllee: String[40];
         FlagsSortie: String[80];
    end;
     
    type TTelegrammeT5 = record
         NoBarre: String[5];
         EtatButee: String[2];
                    // 0 = False : Ouverte
                    // 1 = True : Déployée
    end;
    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

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Février 2010
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 533
    Points : 124
    Points
    124
    Par défaut
    Je suis désolée je ne comprend pas tout.
    C'est à dire sur chaque requête ?

    Sachant que mon SocketHandle sur le récupère sur le ClientRead. Du coup à chaque fois que mon client envoi un message récupération du sockethandle, on lui renvoit la réponse.

    Puis déconnexion du client systématique après chaque réponse reçue.

    Du coup quand il renvoit une trame à nouveau on récupère son sockethandle....
    Windows XP
    Delphi 7

    WinDev Mobile 17

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    bonjour juju,

    je ne comprend pas tout dans ton projet

    1) un client se connecte, tu stockes un ID dans une base de données

    2) sans relation avec le premier évènement tu envoies des données à un client identifié par l'id stocké ci-dessus.

    alors je ne comprend pas bien pourquoi tu passes par la base de donnée, mais en tout état de cause, tu as en mémoire un TClientSocket qui correspond à ta connexion.

    l'enregistrement où tu stockes l'ID possède probablement une clé unique. Si elle est numérique tu peux la placée dans TClientSocket.Tag pour associer les deux. Du coup pour envoyer des données à une connexion, tu cherche le TClientSocket dont le Tag est égale à la clé de ta base.

    si ta clé est plus complexe, tu peux créer un objet encapsulant le tout

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    type
      TConnexionReference = class
        CleBDD : TCleBDD; // la clé de ta base
        Socket : TClientSocket; // la connexion associée
      end;
    tu crée un tel objet à la connexion du client et tu le place dans un liste de connexions actives et tu le détruis sur la déconnexion du client. Et tu ajoutes une fonction de recherche de connexion qui se base sur CleBDD pour retrouver le socket correspondant.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Février 2010
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 533
    Points : 124
    Points
    124
    Par défaut
    Bonjour,

    En fait sur le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure TMainForm.ServerSocketClientRead(Sender: TObject;
    Je récupère l'idconnexion de mon client qui se connecte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     idConnect := Socket.SocketHandle;
    Je le stocke (toujours dans cette même procédure) dans ma bdd mais c'est juste pour pouvoir savoir quel scan est connecté à un instant T en fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        oqInsertIdConnexion.Close;
        oqInsertIdConnexion.SQL.Clear;
        oqInsertIdConnexion.SQL.Add('UPDATE adresseip SET idconnexion = :monIdConnexion WHERE adrip = :addIP');
        oqInsertIdConnexion.DeclareAndSet('monIdConnexion', otString, idConnexion);
        oqInsertIdConnexion.DeclareAndSet('addIP', otString, addIP);
        oqInsertIdConnexion.Execute;
        oqInsertIdConnexion.Session.Commit;
    Et ensuite quand je renvoi la réponse à mon client :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure envoiMsgSocket(IdScan : Integer; sCodeBarre : String; sMessage : String;ServerSocket : TServerSocket; Trace : TMemo);
    Je le renvoi vers le bon id (sans passer par ma bdd) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
       idDeConnexion := IndexHandle(ServerSocket, IdScan);
       iTailleMessage := Length(sMessage);
       ServerSocket.Socket.Connections[idDeConnexion].SendText(IntToStr(iTailleMessage) +CRLF+ sMessage);
    Est ce que je suis plus claire comme ça ?

    Sachant que je n'utilise pas de TClientSocket... juste un TServerSocket, mon programme Delphi est mon serveur, et mes clients Windev Mobile mes clients (ce sont des scans PSION)
    Windows XP
    Delphi 7

    WinDev Mobile 17

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    ok, mais si tu ne passes pas par la BDD pourquoi utilises-tu un idScan au lieu de conserver l'objet Socket que te donnes l'événement onClientRead ?!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    procedure envoiMsgSocket(Socket: TCustomWinSocket; sCodeBarre : String; sMessage : String; Trace : TMemo);
    begin
     iTailleMessage := Length(sMessage);
     Socket.SendText(IntToStr(iTailleMessage) +CRLF+ sMessage);
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Février 2010
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 533
    Points : 124
    Points
    124
    Par défaut
    Parce que le sendText a besoin d'une adresse, je te met en pièce jointe l'erreur générée si je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ServerSocket.Socket.SendText(IntToStr(iTailleMessage) +CRLF+ sMessage);
    Images attachées Images attachées  
    Windows XP
    Delphi 7

    WinDev Mobile 17

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    non pas "ServerSocket.Socket" mais le paramètre "Socket" qui est dans la fonction OnClientRead

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
    
    end;
    au lieu de conserver son Handle, tu conserves l'objet lui-même.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Février 2010
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 533
    Points : 124
    Points
    124
    Par défaut
    J'ai essayé mais ça me met

    SentText identificateur non déclaré pour ce code là dans ma procédure envoiMsgSocket :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       ServerSocket.SendText(IntToStr(iTailleMessage) +CRLF+ sMessage);
    Je teste autre chose du coup avec les ActiveConnections en tant qu'id... je te tiens au courant.
    Windows XP
    Delphi 7

    WinDev Mobile 17

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

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    sinon je vends des prestations de développement...
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  11. #11
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 501
    Points : 24 988
    Points
    24 988
    Par défaut
    Citation Envoyé par juju1988 Voir le message
    Je suis désolée je ne comprend pas tout.
    C'est à dire sur chaque requête ?
    Tu stockes le SocketHandle avec le message, tu le transmets de fonction en fonction comme le CodeBarre !

    La durée de vie de cet ID est tellement court, vu qu'il y a connexion, émission, réception puis déconnexion, cela n'a pas sa place en DB !

    Citation Envoyé par juju1988 Voir le message
    Sachant que mon SocketHandle sur le récupère sur le ClientRead. Du coup à chaque fois que mon client envoi un message récupération du sockethandle, on lui renvoit la réponse.
    As-tu pensé à deux requêtes rapprochées par le client ?
    Comment gère tu le OnRead ?
    Tu traites tout directement dans le OnRead ou tu utilises un thread séparé ?
    Si Thread séparé, il faut gérer les messages simultanés
    Si Tout est dans le OnRead mais présence d'un Application.ProcessMessages dans le code, il y a un risque de ré-entrance

    Cas Thread :
    Client envoie M1
    Serveur reçoit M1 et stocke SH1 lié à IP1
    Serveur ajoute M1 au Thread
    Client envoie M2
    Thread traite M1 (paralèllement)
    Serveur reçoit M2 et stocke SH2 lié à IP1
    Thread a traité M1 et envoie le message à IP1 mais le mauvais handle SH2 ! oups !
    Serveur ajoute M2 au Thread
    Thread traite M2
    Thread a traité M2 et envoie le message à IP1 avec son handle SH2

    Cas ProcessMessages :
    Client envoie M1
    Serveur reçoit M1 et stocke SH1 lié à IP1
    Client envoie M2
    Serveur traite M1
    Serveur durant le traitement de M1, appel ProcessMessages (pour de l'affichage ou je ne sais quoi)
    Comme un OnRead pour M2 est en attente, il y a "ré-entrance" dans OnRead
    Serveur reçoit M2 et stocke SH2 lié à IP1
    Serveur traite M2
    Serveur durant le traitement de M2, appel ProcessMessages (pour de l'affichage ou je ne sais quoi)
    Serveur a traité M2 et envoie le message à IP1 avec son handle SH2
    Serveur a traité M1 et envoie le message à IP1 avec le mauvais handle SH2
    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

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Février 2010
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 533
    Points : 124
    Points
    124
    Par défaut
    Bien tenté

    Du coup ce que j'ai fait sur ServerSocketClientConnect :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        id := ServerSocket.Socket.ActiveConnections -1;
    J'avais déjà utilisé cette solution au tout début cependant j'avais une connexion permanente et du coup en cas de déconnexion d'un scan les id n'étaient plus corrects du tout.
    Maintenant je n'utilise plus une connexion permanente. Le client pose une question ==> connexion, retour de la réponse ==> déconnexion du client. Du coup pour l'instant pas de problème...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ServerSocket.Socket.Connections[id].SendText(IntToStr(iTailleMessage) +CRLF+ sMessage);
    Je vais continuer mes tests cependant avant de valider tout ça.
    Windows XP
    Delphi 7

    WinDev Mobile 17

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 501
    Points : 24 988
    Points
    24 988
    Par défaut
    Tu ne penses à pas l'accès concurrentiel !
    Imagine 5 clients qui envoie tous en même temps ton ActiveConnections - 1 est complètement dans les choux !

    As-tu correctement pris en compte les messages simultanés ?

    IdScan passé à envoiMsgSocket est bien le SocketHandle du OnRead passé de fonction en fonction, tu as pas utilisé de variable globale ou ta DB à un moment donné, tu es sûre de cela ?

    Pourquoi stocker l'ID en DB cela si tu ne l'utilises pas après ?!

    Sinon comme Paul, te le propose, tu peux utiliser le TCustomWinSocket Socket provenant de OnRead si tu fais tout ton traitement durant le OnRead !
    Faut penser que durant tout le traitement, les messages suivants s'accumulent dans le tampon tant que tu bloques OnRead



    Evidemment, si tu utilises un thread qui sépare le OnRead du traitement, il y a un risque de libération de l'objet et c'était le rôle du SocketHandle qui évitait d’éventuelles Violation d'Accès !
    Je n'ai utilisé SocketHandle uniquement parce qu'il tout était asynchrone (OnRead dans le thread VCL, Parsage, Traitement et SendText chacun dans un thread séparé, et l'accès à Connections[] était en Synchronize)

    Dans mon cas, les connexions étaient permanentes, pendant plusieurs heures, cela pouvait échanger un petit million de message, cela n'allait pas en plus passé son temps à se déconnecter\reconnecter
    Mais il fallait tout de même gérer les déconnexions (on ne sait jamais) puis reconnexion par un autre socket (et cela gérait, si le message n'avait pas dépassé son temps de vie et qu'un port se déclairait comme receveur d'une catégorie de message, une ré-émission des réponses en attente)

    Effectivement, mon OnRead ne faisait que découper un message de forme STX Data ETX et l'ajoutait dans une liste pour parsage, le OnRead pouvant contenir plusieurs messages ou des messages partiels
    Cas rarissime mais cela pouvait se produire lorsque plus de 8Ko était reçu simultanément, en prod, je crois que le flux n'était pas suffisant pour y arriver justement parce que OnRead ne bloquait qu'un temps très très limité, même pas 100µs le temps de l'ajout dans la liste, je faisais en sorte de bloquer les ThreadList, le moins de temps que possible
    Ensuite, le traitement, lui devait se faire en moins de 250 ms (en réalité, j'avais 2 secondes, mais si je dépassais 250, le retard s'accumulait de message en message et l'on pouvait alors finir par avoir du retard sur les 2 secondes, sans compter la gestion du ACK, qui devait être quasi-immédiate)

    Ensuite, le thread de parsage découpait le message pour l'ajouter à un thread de traitement qui effectuait les opérations nécessaires
    Cela gérait environ entre 4 à 10 messages par secondes d'une taille entre 128o et 2Ko, le plus long étant les 2 à 10 SQL provoqués par chaque message
    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

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Février 2010
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 533
    Points : 124
    Points
    124
    Par défaut
    Le ActiveConnections n'était effectivement pas la solution je suis donc repassée sur le sockethandle.
    Et en fait je n'ai plus de problème... c'est mon stockage en base de données qui m'a induit en erreur je ne remettais pas à vide mon idconnexion au bon moment et ce qui m'a fait pensé à une erreur d'idconnexion mais non pas du tout.
    Ce que tu m'avais donné Shai fonctionne très bien.
    Windows XP
    Delphi 7

    WinDev Mobile 17

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 28/09/2010, 15h04
  2. Réponses: 1
    Dernier message: 02/03/2008, 22h04
  3. Problème sur GetPrivateProfileString ???
    Par Bordelique dans le forum Langage
    Réponses: 7
    Dernier message: 25/06/2003, 22h15
  4. Problème sur une requête INSERT
    Par Marion dans le forum Langage SQL
    Réponses: 3
    Dernier message: 17/06/2003, 08h45
  5. problème sur une requête!!!!!
    Par Mcgrady_01 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 13/06/2003, 01h17

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