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

Composants VCL Delphi Discussion :

TTcpServer, OnAccept et TCustomIpClient


Sujet :

Composants VCL Delphi

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 88
    Points : 53
    Points
    53
    Par défaut TTcpServer, OnAccept et TCustomIpClient
    Bonjour,

    J'essaie de réaliser un échange de texte entre un client TTcpClient et un serveur TTcpServer (sans utiliser les composants Indy).
    Le serveur est ouvert à la creéation d'un thread. Quand le client se connecte au serveur, l'évènement OnAccept est bien lancé et la préocédure éxécutée avec une affectation du paramètre ClientSocket envoyé par l'évènement à l'objet ServerClientSocket. Seulement, lors de l'éxécution du thread, j'ai une exception EAccessViolation qui intervient au moment de l'utilisation de la procédure ReceiveIn sur ServerClientSocket.
    J'aimerais savoir pourquoi ca arrive ?
    Qu'est ce que je manque ?
    Les objets sont pourtant construit et l'affectation valide.
    Merci d'avance de vos réponses

    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
     
     
    unit Unit3;
     
    interface
     
    uses
      Classes, Dialogs, sockets;
     
    type
      TServerThread = class(TThread)
        TcpServer1: TTcpServer;
        procedure TcpServer1Accept(Sender: TObject; ClientSocket: TCustomIpClient);
        constructor Create();
      private
        { Private declarations }
      protected
        procedure Execute; override;
      end;
     
    var
      ServerClientSocket:TCustomIpClient;
     
    implementation
     
    constructor TServerThread.Create();
    begin
      inherited Create(True);
      TcpServer1:=TTcpServer.Create(nil);
      TcpServer1.LocalHost:='127.0.0.1';
      TcpServer1.LocalPort:='10000';
      TcpServer1.BlockMode:=bmThreadBlocking;
      TcpServer1.OnAccept:=TcpServer1Accept;
      TcpServer1.Open;
    end;
     
    procedure TServerThread.Execute;
    var
      s:string;
    begin
      while Not Terminated do
      begin
        s:='';
        while s='' do
        begin
          s:=s+ServerClientSocket.Receiveln;
        end;
        ShowMessage(s);
      end;
    end;
     
    procedure TServerThread.TcpServer1Accept(Sender: TObject; ClientSocket: TCustomIpClient);
    begin
      ServerClientSocket:=TCustomIpClient.Create(nil);
      ServerClientSocket:=ClientSocket;
      Resume();
    end;
     
    end.

  2. #2
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Bonjour,

    Il me semble qu'au Create du thread il faudrait rajouter l'instruction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TcpServer1.CreateSuspended:=true ;
    afin que la procedure "Execute" n'ait pas immédiatement la main en sortie du "Create" et attende le "Resume".
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 88
    Points : 53
    Points
    53
    Par défaut
    Re,

    Normalement, le thread est crée en état suspendu lors de l'appel a Create à cause de la ligne "inherited Create(True)".
    Dans le doute, j'ai fait l'essai en utilisant la méthode Suspend mais j'obtiens le même résultat.
    Au fait, la propriété CreateSuspended n'existe pas pour l'objet TThread et si elle existait, ne pourrait pas s'appliquer au TTcpServer.
    Merci quand même d'avoir répondu ! ^^
    Quelqu'un a t'il une autre idée ?

  4. #4
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Rebonjour,

    Désolé pour cette erreur. Peut-être le problème vient-il de l'instruction "TcpServer1.BlockMode:=bmThreadBlocking" à remplacer par
    "TcpServer1.BlockMode:=bmBlocking".
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 88
    Points : 53
    Points
    53
    Par défaut
    Re,

    J'ai fait des essais avec les sockets bloquants et non bloquants. Je n'ai plus cette erreur de violation d'accès mais par contre le serveur ne répond plus aux évènements OnAccept et la procédure TcpServerAccept ne s'éxécute plus lors de la connection d'un client ..... ce qui est encore plus emmerdant.


    D'autres idées ?

  6. #6
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Re,

    A propos, l'instruction "ServerClientSocket:=TCustomIpClient.Create(nil);" est en trop. Mais à part perdre de la mémoire, elle ne devrait pas géner.
    Par contre, le code ne fonctionne que pour un seul client.
    Si il y a plusieurs clients, il faudrait une liste de TCustomIpClient et gérer les déconnections.

    Autre piste, mettre un try ... except dans l'Execute.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 88
    Points : 53
    Points
    53
    Par défaut
    Re ....

    J'ai enlevé l'instruction "ServerClientSocket:=TCustomIpClient.Create(nil);" et elle ne change effectivement rien.
    Sinon, oui, le code n'est prévu que pour un seul client.
    J'ai mis du try....except dans la procédure Execute et il j'ai bien l'exception de soulevée dans le ligne qui utilise la méthode ReceiveIn.

    Je me suis posé la question suivante .... Dans la procédure de gestion de l'évènement OnAccept, est-ce-que le paramètre ClientSocket contient l'objet lui même (passage par valeur) ou son adresse (passage par référence) ?
    Si c'est un passage par adresse, le ClientSocket serait détruit en fin de procédure et donc la variable ServerCLientSocket pointerait sur un objet non existant en mémoire ce qui causerait l'AccessViolation.
    Qu'est-ce-que vous en pensez ? Je n'ai pas trouvé de documentation à ce sujet.
    Si c'est un passage par valeur, alors j'en sais vraiment rien

  8. #8
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Bonjour,

    Tous les objets sont systèmatiquement passés par adresse.

    Pour debugger, Essaye de mettre dans Execute l'instruction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    If serverclientsocket.connected then showmessage('Connected') else showmessage('Not connected');
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 88
    Points : 53
    Points
    53
    Par défaut
    Alors, j'ai essayé cette ligne et il m'indique "not connected".
    J'ai essayé d'accéder à d'autre méthodes ou propriétés de ServerClientSocket dans la procédure éxécute mais à chaque fois qu'il y a un accès à ServerClientSocket, j'ai l'exception EAccessViolation. Ce qui semblerait signifier que ServerClientSocket ne contient qu'un pointeur vers l'adresse de ClientSocket, lui-même détruit en fin de la procédure Accept.
    Lors de l'affectation "ServerClientSocket:=ClientSocket;", est-ce-que ServerClientSocket contient une copie de l'objet ClientSocket ou alors seulement un pointeur vers ClientSocket ?
    S'il contient une adresse, comment est-il possible de dupliquer l'objet ClientSocket ?

  10. #10
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Bonjour,

    On avance : si tu as "Not connected", il faut attendre que ce soit connecté avant de faire le ReceiveLn. En fait, le "Resume" devrait se faire seulement sur l'événement onConnect du client, mais le test de l'état connected devrait normalement suffire.

    L'object clientSocket est créé automatiquement lors de la connection client. D'une facon générale, on peut cloner des objets via la methode Assign, lorsqu'elle existe. Dans ce cas, il ne faut surtout pas le faire.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    88
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 88
    Points : 53
    Points
    53
    Par défaut
    Bonjour,

    J'ai rajouté la ligne suivante dans les procédures "execute" et "accept" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ShowMessage(ServerClientSocket.LocalHost+ServerClientSocket.LocalPort+
    ServerClientSocket.RemoteHost+ServerClientSocket.RemotePort);
    Dans la prodédure "accept", j'ai bien les données par contre dans la procédure "execute", j'obtiens une EAccessViolation.
    En fait, dès que j'essaie d'accéder à une méthode ou une propriété, j'ai cette exception.
    Bizarrement, l'accès à la propriété Connected fonctionne quand j'essaie de mettre la ligne suivante dans "execute" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if ServerClientSocket.Connected the s:='true' else s:='false';
    ShowMessage(s);

Discussions similaires

  1. [TTcpServer/Client] Recherche cours/tuto/exemples
    Par prgasp77 dans le forum Composants VCL
    Réponses: 7
    Dernier message: 26/02/2010, 10h16
  2. TtcpServer - code interdit dans OnAccept ?
    Par gaby277 dans le forum Web & réseau
    Réponses: 3
    Dernier message: 12/02/2009, 23h07
  3. Réponses: 3
    Dernier message: 16/11/2007, 17h39
  4. [MFC][CAsyncSocket] OnAccept
    Par corwin_d_ambre dans le forum MFC
    Réponses: 4
    Dernier message: 16/02/2006, 11h34

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