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 :

Reception de packet UDP


Sujet :

C++Builder

  1. #1
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 24
    Points : 16
    Points
    16
    Par défaut Reception de packet UDP
    Salut,
    J'utilise le composant TUDPSocket pour envoyer et recevoir des packets UDP,
    l'envoi se fait sans problème mais la réception pose problème, Je ne reçois par les données pourtant elle sont bien présente sur le réseau.
    Voici mon code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void __fastcall TForm1::UdpSocket1Receive(TObject *Sender, PChar Buf,
          int &DataLen)
    {
          AnsiString Trame;
           UdpSocket1->ReceiveBuf(Trame,UdpSocket1->BytesReceived,1);
          Memo1->Text=IntToStr(Trame.Length());//Affichage de la longueur des donnés
          Memo3->Lines->Add("Donnée recues "+Trame);//Affichage datas
    }
    Ça à l'air tout con et pourtant je bute dessus donc j'implore votre aide lol
    Merci d'avance
    cordialement.

  2. #2
    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
    Salut taquilla, j'ai trouvé du code qui pourrais peut-être t'aider, alors le voici:

    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
    BYTE buffer[4096];
     
    Memo1->Clear();
    UdpSocket1->Connect();
    Memo1->Lines->Add(" Local " + String(UdpSocket1->LocalPort) + " Remote " + String(UdpSocket1->RemotePort));
    //...
    int NumRead = UdpSocket1->ReceiveBuf(buffer, sizeof(buffer), 0);
    if( NumRead >= sizeof(DataHeader) )
    {
        DataHeader *pHdr = (DataHeader*)buffer;
     
        Memo1->Lines->Add(String(5000+pHdr->sender)+" "+
            String(pHdr->msgId)+" "+String(pHdr->msgLen)+" "+
            String(NumRead-sizeof(DataHeader)));
    }
    PS: J'ai pas testé
    • 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

  3. #3
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 24
    Points : 16
    Points
    16
    Par défaut
    Merci de ta réponse
    mais malheureusement il ne fonctionne pas
    A+

  4. #4
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 24
    Points : 16
    Points
    16
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void __fastcall TForm1::UdpSocket1Receive(TObject *Sender, PChar Buf,
          int &DataLen)
    {
     
     
     
    }
    En réalité il n'y a pas d'événement qui arrive, donc la routine ne peut pas s'exécuter.
    Par contre pour l'envoi, il y a bien un événement qui est envoyé .
    J'ai regardé plusieurs exemples sur le net, et ils utilisent plus ou moins la même technique et apparemment je suis pas le seul à avoir ce souci .
    A+

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bonjour bonjour,
    j'ai exactement le même problème sous Delphi 7, et je viens de m'inscrire à l'instant pour demander de l'aide, après avoir cherché autant que je pouvais.

    J'utilise le socket UDP fourni dans Delphi 7.

    C'est exactement pareil : mes trames envoyées sont bien sur le réseau, un événement d'envoi est bien activé, mais pas l'événement de réception. Je vais lire avec attention vos réponses, en espérant une solution !
    (ah pardon : je vois que je fais remonter une ancienne discussion, qui date de l'année dernière ; désolé)

  6. #6
    Membre à l'essai
    Inscrit en
    Juillet 2007
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 24
    Points : 16
    Points
    16
    Par défaut
    Salut,
    non non la discution est bien récente, je sais qu'avec delphi ont n'a les mêmes composants, par contre il y a beaucoup plus d'exemples, je me suis basé dessus pour essayer de résoudre mon problème mais c'est toujours pareil.
    Je te tiens au courant si je trouve quelque chose
    A+

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 4
    Points : 7
    Points
    7
    Par défaut
    salut à vous.
    Apparement, depuis toutes ces années, il n'y a pas eu de solution. TUdpSocket n'arriverait -il pas à récéptionner des trames? C'est quand même balot d'être coincé comme ca!

  8. #8
    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
    Hello
    ce composant est complétement buggé
    il avait au départ été conçu pour la CLX
    utilise à la place les composants Indy ou ceux de Francois Piette (OverByte)
    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

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 4
    Points : 7
    Points
    7
    Par défaut
    Merci de l'info, comme ca c'est plus clair .

    J'avais regardé les possibilités de Indy, effectivement ca marche mieux, mais on est obligé d'utiliser 2 objets Server & Client si on veut Lire & écrire.

    Enfin, tant qu'on utilise l'objet tel quel dans une fiche ca va, mon problème c'est que je veux l'utiliser dans une classe de ma DLL, et là ca se complique!
    Je n'arrive pas a instancier TIdUDPClient comme membre de ma classe, le compilo m'insulte par rapport à certains membres de classe parente de TIdUDPClient !!!

    Si tu as une idée là dessus je suis preneur.
    Merki

  10. #10
    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
    Essaye les composants de François Piette (Overbyte) http://www.overbyte.be/frame_index.html
    pour inserer une Form dans une DLL sur laquellle tes composants seront déposés http://bcbjournal.org/articles/vol2/...m_in_a_DLL.htm

    ou alors utilise simplement les API de MS tu devrais trouver des exemples sur le Net

    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

  11. #11
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Points : 356
    Points
    356
    Par défaut
    On aura beau me dire qu'il est inutile de réinventer la roue, mais il reste que quand on veut faire de la programmation de bas niveau, on est jamais mieux servi que par soi-même.Les primitives sont là, faut juste les adapter à ses besoins.

    Je me suis lancé récemment en programmation Java/Andoid et je me suis écrit un "TUdpSocket" qui contient l'essentiel, soit un "Send" pour la transmission et l'équivalent d'un événement "OnReceive" pour la réception. J'ai été étonné de voir que c'était pas si compliqué.

    http://guytprog.blogspot.ca/2012/04/...pas-de_14.html

    Évidemment, tout est toujours plus compliqué sous Windows, mais je suis tombé là-dessus et quelque chose me dit que la montagne, elle n'est pas si haute, finalement.

    http://www.adp-gmbh.ch/win/misc/sockets.html

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Par défaut le composant est en BlockMode bmBlocking et ne reçoit pas l'évènement OnReceive !

    Il faut créer un thread qui lit en boucle le TWinSocketStream
    On attend la présence de donnée avec WaitForData puis on lit avec Read\ReadBuffer

    Pour activer OnReceive, il faut passer BlockMode à bmNonBlocking !

    Personne ne l'a mentionné, c'est peut-être trivial et j'espère que cela a déjà été testé !
    Mais parfois, c'est les trucs de bases qui coincent !

    Sinon, à partir de Delphi 7, il faut effectivement utiliser les composants Indy
    Cela fait 10 ans que TClientSocket, TServerSocket et TUdpSocket sont déclarés obsolètes pourtant ils ont été migré en XE2 et sont toujours maintenus !
    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

  13. #13
    Futur Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 4
    Points : 7
    Points
    7
    Par défaut
    Bonjour,

    D'accord avec toi Guyt54. Faut juste adatper. D'ailleur merci pour ton forum sur lequel j'étais tombé (aie) et dont je m'étais inspiré.

    Merci aux autres pour vos précisions, j'ai matière à réfléchir maintenant.
    Y a plus qu'à, surtout coté Thread ?!? Mais pas tout saisi :puisqu'il y aurait un thread qui scrute si y a quelques choses à lire, pourquoi waitfordata?

    Je vous tiens au courant de ma solution trouvé qu'on ferme ce topic une bonne fois pour toute ! ;-)

    Bonne journée

  14. #14
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Points : 356
    Points
    356
    Par défaut
    en tout cas, festinno, il est motivant, ton post.

    je travaille depuis hier à l'écriture d'un UDP socket, comme je m'en doutais, c'est pas évident.

    Là, je viens de tomber là-dessus:

    http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx

    Tu regarderas l'exemple, pour une fois que Microsoft nous en donne un pas mal.

  15. #15
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Points : 356
    Points
    356
    Par défaut
    YES!!!!!!!!!!!!!!!!


    J'ai adapté l'exemple de microsoft. c'est très lourd pour l'instant, mais la transmission UDP fonctionne, ça nous donne une bonne base de travail pour faire du code plus intelligent.
    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
     
    AnsiString UdpSend(AnsiString data, AnsiString ipAddr, int port)
    // http://msdn.microsoft.com/en-us/library/windows/desktop/ms737625%28v=vs.85%29.aspx
    {
        AnsiString mes ;
        int iResult ;
     
        // Initialize Winsock
        WSADATA wsaData;
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != NO_ERROR)
        {
            mes.sprintf("WSAStartup function failed with error: %d",iResult) ;
            return mes ;
        }
     
        // Create a SOCKET for connecting to server
        SOCKET ConnectSocket;
        ConnectSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
        if (ConnectSocket == INVALID_SOCKET)
        {
            mes.sprintf("socket function failed with error: %ld", WSAGetLastError());
            WSACleanup();
            return mes ;
        }
     
        // The sockaddr_in structure specifies the address family,
        // IP address, and port of the server to be connected to.
        sockaddr_in clientService;
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr(ipAddr.c_str());
        clientService.sin_port = htons(port);
     
         // Connect to server.
        iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService));
        if (iResult == SOCKET_ERROR)
        {
            mes.printf("connect function failed with error: %ld", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            return mes ;
        }
        // Send data
         send(ConnectSocket,data.c_str(),data.Length(),0) ;
         ShowMessage("data transmitted") ;
        // Close
        closesocket(ConnectSocket);
        WSACleanup();
        return "DONE!!!" ;
    }
    Je regarde côté réception, maintenant.

    C'est vraiment mon jour de chance:

    http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx

    et aussi:
    http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx

    finalement:
    http://www.win32developer.com/tutori...utorial_3.shtm

  16. #16
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Points : 356
    Points
    356
    Par défaut
    Bon, le UDP en réception fonctionne (mode non-blocking).

    Encore une fois, du code adapté à partir d'un exemple de Microsoft:

    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
     
    AnsiString UdpGet(int listenPort,AnsiString& rxData, AnsiString& ipAddr, int& port)
    // recvfrom failed with error 10035
    {
        AnsiString mes ;
        int iResult ;
     
        // Initialize Winsock
        WSADATA wsaData;
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != NO_ERROR)
        {
            mes.sprintf("WSAStartup function failed with error: %d",iResult) ;
            return mes ;
        }
     
        // Create a receiver socket to receive datagrams
        SOCKET RecvSocket ;
        RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (RecvSocket == INVALID_SOCKET)
        {
           mes.sprintf("socket function failed with error: %ld", WSAGetLastError());
           WSACleanup();
           return mes ;
        }
        // Set to non-blocking mode
    	   u_long iMode=1;   // If iMode!=0, non-blocking mode is enabled.
    	   ioctlsocket(RecvSocket,FIONBIO,&iMode);
     
        // Bind the socket to any address and the specified port.
        sockaddr_in RecvAddr;
        RecvAddr.sin_family = AF_INET;
        RecvAddr.sin_port = htons(listenPort);
        RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        iResult = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
        if (iResult != NO_ERROR)
        {
            mes.printf("bind failed with error %d\n", WSAGetLastError());
            closesocket(RecvSocket);
            WSACleanup();
            return mes ;
        }
       // Ready to read data
       char RecvBuf[256] ;
       int  BufLen = 255 ;
       int  DataCount ;
       sockaddr_in SenderAddr;
       int SenderAddrSize = sizeof(SenderAddr) ;
       // tell user to send data in modal ok dialog
       ShowMessage("Ready to receive data, press ok when data transmitted (or not!)") ;
       // read data
       int retries = 0 ;
       do
       {
         DataCount = recvfrom(RecvSocket,RecvBuf, BufLen, 0,
                             (SOCKADDR*)&SenderAddr, &SenderAddrSize);
         retries++  ;
         Sleep(1000) ;
       }
       while (DataCount < 0  && retries < 5) ;
       if (DataCount > 0)  // -1  if error
       {
         RecvBuf[DataCount] = 0 ;
         rxData = AnsiString(RecvBuf) ;
         mes = "OK" ;
       }
       else
       {
         mes.sprintf("recvfrom failed with error %d", WSAGetLastError()) ;
       }
       // Close
       closesocket(RecvSocket);
       WSACleanup();
       return mes ;
    }
    Reste plus qu'à intégrer tout ça dans un composant facile d'utilisation, la roue aura été réinventée, mais le UDP démystifié.

  17. #17
    Futur Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2012
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 4
    Points : 7
    Points
    7
    Par défaut
    Salut,

    pas si lourd que ca le code à intégrer, assez facile de compréhension une fois qu'on l'a sous les yeux, mais ce n'est pas une démarche que j'aurai inventé.

    Merci pour les explications et les liens associés (aussi important).

    Pour ma part, l'envoi UDP fonctionne aussi très bien avec winsock, comme j'avais pu le faire en utilisant une instance de TUDPSocket.

    Par contre j'ai quelques soucis encore avec la réception de données...
    affaire à suivre...

    En tout cas merci pour les exemples Guyt54 et MS un peu aussi. ;-)

  18. #18
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Points : 356
    Points
    356
    Par défaut
    Et voilà, la transmission/réception UDP en un seul composant que j'ai appelé "TUdpSockit" comme dans "Sock it to me".

    Une propriété réellement importante, "ListenPort" pour le port de réception.

    Deux méthodes pour la la transmission (Send et SendString)

    Deux événements (exclusif) pour la réception "OnRxUdpData" et "OnRxUdpString".

    UdpSockit.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
    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
    77
    78
    79
    80
    81
    82
     
    // UdpSocket.h
     
    #ifndef UdpSockitH
    #define UdpSockitH
     
    #include <SysUtils.hpp>
    #include <Classes.hpp>
    #include <WinSock2.h>
     
    typedef void __fastcall (__closure *TRxUdpDataEvent)(TObject* Sender,
                                                         void* dest,
                                                         int count,
                                                         AnsiString fromIP,
                                                         int fromPort) ;
     
    typedef void __fastcall (__closure *TRxUdpStringEvent)(TObject* Sender,
                                                           AnsiString data,
                                                           AnsiString fromIP,
                                                           int fromPort);
     
    class PACKAGE TUdpSockit : public TComponent
    {
     
      public:
       // Constructeur et destructeur
     
      __fastcall TUdpSockit(TComponent* owner) ;
    	 virtual _fastcall ~TUdpSockit(void) ;
      bool Send(AnsiString ipAddr, int port, const void* data, int count) ;
      bool SendString(AnsiString ipAddr, int port, AnsiString stg) ;
      AnsiString GetErrorMes(void) ;
     
      private:
      AnsiString fErrorMes ;
      bool fDllLoaded ;
      TRxUdpDataEvent fOnRxUdpData ;
      TRxUdpStringEvent fOnRxUdpString ;
     
      // Gestion réception
      SOCKET fRxSocket ;
      sockaddr_in fSenderAddr;
      int fSenderAddrSize ;
      int fListenPort ;
      char* fRxBuf ;
      int   fRxBufSize ;
      int   fRxCount ;
     
      bool InEditMode(void) ;
      void DisableReceptionHandling(void) ;
      void ResetReceptionHandling(void) ;
      bool EnableReceiveSocket(void) ;
      bool ReadRxSocket(void) ;
     
      	// Gestion Timer
      int fTimerID ;
    	 int fPollingInterval ; // in millisec
      static void __stdcall TimerCallBackProc(UINT uTimerID, UINT uMessage, ULONG dwUser,
    												                            		ULONG dw1, ULONG dw2) ;
       void TimerHandler(void) ;
     
      // Gestion propriétés
      void __fastcall SetPollingInterval(int val) ;
      void __fastcall SetListenPort(int val) ;
      void __fastcall SetRxBufSize(int val) ;
      void __fastcall SetOnRxUdpData(TRxUdpDataEvent event) ;
      void __fastcall SetOnRxUdpString(TRxUdpStringEvent event) ;
     
      __published:
      __property int PollingInterval = {read=fPollingInterval,
                                        write=SetPollingInterval, default=50 } ;
     
      __property int ListenPort = {read=fListenPort, write=SetListenPort, default=1954 } ;
      __property int RxBufSize = {read=fRxBufSize, write=SetRxBufSize, default=1024} ;
      __property TRxUdpDataEvent OnRxUdpData = { read=fOnRxUdpData, write=SetOnRxUdpData } ;
      __property TRxUdpStringEvent OnRxUdpString = { read=fOnRxUdpString,
                                                      write=SetOnRxUdpString} ;
     
      protected:
      void virtual __fastcall Loaded(void) ;
    };
    #endif
    UdpSockit.cpp:
    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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
     
    /*
    ================================================================================
    Composant TUdpSockit (Sock it to me)
    Guy Tessier, mai 2012
     
    librairie Windows requise: ws2_32.lib
    Réception/Transmission internet protocole UDP
     
    Propriétés:
    ----------
     
    ListenPort:      Port utilisé pour la réception
    PollingInterval: Intervalle du timer interne utilisé pour la réception
                      en milliseconde (défaut: 50ms, précision 1 ms)
    RxBufSize:       Grosseur maximum des paquets UDP (défaut= 1024)
     
    Méthodes:
    --------
     
    bool SendString(AnsiString ipAddr, int port, AnsiString stg) ;
    bool Send(AnsiString ipAddr, int port, const void* data, int count) ;
     
    Transmission de chaine ou de données brutes à l'adresse et au port UDP
    précisé. Indique si réussi. Si erreur on aura plus de détail en appelant
    la méthode "GetErrorMes"
     
    Événements (sur réception):
    --------------------------
     
    // L'un ou l'autre (mais pas les deux!)
    void __fastcall fUdpSocketRxUdpString(TObject *Sender, AnsiString data,
                                          AnsiString fromIP, int fromPort)
     
    void __fastcall fUdpSocketRxUdpData(TObject *Sender, void *dest, int count,
                                        AnsiString fromIP, int fromPort)
    Un message à l'écran apparaitra en cas d'erreur de connexion avec soncket
    interne.
    ================================================================================
    */
     
    #pragma hdrstop
     
    #include "UdpSockit.h"
    #include <dialogs.hpp>
     
    #pragma package(smart_init)
     
    static inline void ValidCtrCheck(TUdpSockit *)
    {
     new TUdpSockit(NULL);
    }
    namespace Udpsockit
    {
      void __fastcall PACKAGE Register()
      {
        TComponentClass classes[1] = {__classid(TUdpSockit)};
        RegisterComponents("Guyt", classes, 0);
      }
    }
     
    // ========
    // Messages
    // ========
     
    const AnsiString  MES_RX_SOCKET_ERR = "Erreur critique lors de l'initialisation"
                                          " du socket de réception UDP" ;
    const AnsiString  MES_TX_SOCKET_ERR = "Erreur de création socket de transmission" ;
    const AnsiString  MES_LOAD_DLL_ERR = "Erreur WinSock DLL" ;
    const AnsiString  MES_TX_CONNECT_ERR = "Erreur connexion socket transmission" ;
     
    // ===========================
    // Constructeur et destructeur
    // ===========================
     
     __fastcall TUdpSockit::TUdpSockit(TComponent* owner) : TComponent(owner)
     {
        WSADATA wsaData;
        fDllLoaded = WSAStartup(MAKEWORD(2, 2), &wsaData) == NO_ERROR ;
        fPollingInterval = 50 ;
        fListenPort = 1954;
        fRxBufSize = 1024 ;
        fSenderAddrSize = sizeof(sockaddr_in) ;
        fOnRxUdpString = NULL ;
     }
     
     _fastcall TUdpSockit::~TUdpSockit(void)
     {
       DisableReceptionHandling() ;
       if (fDllLoaded)
          WSACleanup();
     }
     
    void __fastcall  TUdpSockit::Loaded(void)
    // Appelé au lancement de l'application
    // Les proriétés et événements ont été intialisées
     
     
    {
       TComponent::Loaded() ;
       if (!InEditMode())
            ResetReceptionHandling() ;
    }
     
     // ==================
     // Méthodes publiques
     // ==================
     
     AnsiString TUdpSockit::GetErrorMes(void)
     {
       return fErrorMes ;
     }
     
     bool TUdpSockit::Send(AnsiString ipAddr, int port, const void* data, int count)
     {
         // Vérifier si DLL installé
         if (!fDllLoaded)
         {
           fErrorMes = MES_LOAD_DLL_ERR ;
           return false ;
         }
     
         // Créer un socket
         SOCKET txSocket;
         txSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
         if (txSocket==INVALID_SOCKET)
         {
           fErrorMes = MES_TX_SOCKET_ERR ;
           return false ;
         }
     
         // Spécifier l'adresse du destinataire
        sockaddr_in clientService;
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr(ipAddr.c_str());
        clientService.sin_port = htons(port);
     
        // connexion au serveur
        if( connect(txSocket, (SOCKADDR *) & clientService,
                     sizeof (clientService)) == SOCKET_ERROR)
        {
          fErrorMes = MES_TX_CONNECT_ERR ;
          return false ;
        }
     
       // Transmet données (blocking mode)
       send(txSocket,(const char*)data,count,0) ;
     
       // ferme socket
       closesocket(txSocket);
       return true ;
    }
     
    bool TUdpSockit::SendString(AnsiString ipAddr, int port, AnsiString stg)
    {
      return Send(ipAddr,port,stg.c_str(),stg.Length()) ;
    }
     
    // ================
    // Méthodes privées
    // ================
     
    // -----------------
    // Gestion réception
    // -----------------
     
    bool TUdpSockit::InEditMode(void)
    {
       return ComponentState.Contains(csDesigning) ;
    }
     
     
    void TUdpSockit::DisableReceptionHandling(void)
    {
      if (fTimerID)
       {
         timeKillEvent(fTimerID);
         fTimerID = NULL ;
       }
      if (fRxSocket)
      {
         closesocket(fRxSocket);
         fRxSocket = NULL ;
      }
      if (fRxBuf)
      {
         delete []fRxBuf ;
         fRxBuf = NULL ;
      }
    }
     
    void TUdpSockit::ResetReceptionHandling(void)
    {
      bool isRequired ;
     
      DisableReceptionHandling() ; // on fait le grs ménage
      isRequired = (fOnRxUdpString || fOnRxUdpData) ;
      if (isRequired)
      {
        if (EnableReceiveSocket())
        {
          fRxBuf = new char[fRxBufSize+1] ; // + 1 pour un NULL éventuel
          fTimerID = timeSetEvent(fPollingInterval, 0, TimerCallBackProc, (
                                  ULONG)this, TIME_PERIODIC);
        }
        else
        {
           ShowMessage(MES_RX_SOCKET_ERR) ;
        }
      }
    }
     
    bool TUdpSockit::EnableReceiveSocket(void)
    {
       bool ok ;
     
       ok = fDllLoaded ;
       if (ok)
       {
         fRxSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
         ok = (fRxSocket != INVALID_SOCKET) ;
         if (ok)
         {
           u_long iMode=1;   // If iMode!=0, non-blocking mode is enabled.
    	      ioctlsocket(fRxSocket,FIONBIO,&iMode);
           // Bind the socket to any address and the specified port.
           sockaddr_in RecvAddr;
           RecvAddr.sin_family = AF_INET;
           RecvAddr.sin_port = htons(fListenPort);
           RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
           ok  = bind(fRxSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr)) == NO_ERROR;
           if (!ok)
             closesocket(fRxSocket);
         }
        if (!ok)
          fRxSocket = NULL ;
     
      }
      return ok ;
    }
     
     
    bool TUdpSockit::ReadRxSocket(void)
    // lecture mode non-blocking
    {
      int senderAddrSize ;
      fRxCount = 0 ;
      if (!fRxSocket)
        throw "erreur critique: échec lecture socket" ;
      fRxCount = recvfrom(fRxSocket,fRxBuf,fRxBufSize, 0,
                          (SOCKADDR*)&fSenderAddr, &fSenderAddrSize);
      if (fRxCount < 0) // erreur non-critique ou pas de données
        fRxCount = 0 ;
      return (fRxCount > 0) ;
    }
     
    // -------------
    // Gestion Timer
    // -------------
     
    void __stdcall TUdpSockit::TimerCallBackProc(UINT uTimerID, UINT uMessage,
                                                 ULONG dwUser,
    					                            		          ULONG dw1, ULONG dw2)
    {
      TUdpSockit* This = (TUdpSockit*) dwUser;
      This->TimerHandler();
    }
     
    void TUdpSockit::TimerHandler(void)
    // Validé si événement attaché
    {
      if (ReadRxSocket())
      {
         AnsiString ipAddr = AnsiString(inet_ntoa(fSenderAddr.sin_addr)) ;
         int port = fSenderAddr.sin_port ;
         if (fOnRxUdpString)
         {
            fRxBuf[fRxCount] = 0 ;
            fOnRxUdpString(this,AnsiString(fRxBuf),ipAddr,port) ;
            return ;
         }
         if (fOnRxUdpData) // insécurité
         {
            fOnRxUdpData(this,fRxBuf,fRxCount,ipAddr,port) ;
         }
      }
    }
     
    // ------------------
    // Gestion propriétés
    // ------------------
     
    void __fastcall TUdpSockit::SetPollingInterval(int val)
    {
      fPollingInterval = val ;
      if (!InEditMode())
       ResetReceptionHandling() ;
    }
     
    void __fastcall TUdpSockit::SetListenPort(int val)
     {
       fListenPort = val ;
       if (!InEditMode())
        ResetReceptionHandling() ;
     }
     
    void __fastcall  TUdpSockit::SetRxBufSize(int val)
    {
       fRxBufSize = val ;
       if (!InEditMode())
        ResetReceptionHandling() ;
    }
     
    void __fastcall TUdpSockit::SetOnRxUdpData(TRxUdpDataEvent event)
    {
      fOnRxUdpData = event ;
      if (!InEditMode())
       ResetReceptionHandling() ;
    }
     
    void __fastcall TUdpSockit::SetOnRxUdpString(TRxUdpStringEvent event)
    {
      fOnRxUdpString = event ;
      if (!InEditMode())
       ResetReceptionHandling() ;
    }

  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
    Hello
    Beau Travail Guyt
    malheureusement ne fonctione pas à partir de XP
    les Fonctions timeKillEvent et timeSetEvent de la library Winmm.lib.
    sont comme tu peux le lire
    Windows XP: Included in Windows XP only.
    Header: Declared in Mmsystem.h; include Windows.h.
    Library: Use Winmm.lib.

    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

  20. #20
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Points : 356
    Points
    356
    Par défaut
    Citation Envoyé par DjmSoftware Voir le message
    Hello
    Beau Travail Guyt
    malheureusement ne fonctione pas à partir de XP
    les Fonctions timeKillEvent et timeSetEvent de la library Winmm.lib.
    sont comme tu peux le lire
    Windows XP: Included in Windows XP only.
    Header: Declared in Mmsystem.h; include Windows.h.
    Library: Use Winmm.lib.

    cdlt
    ça me surprend ce que me dis. les deux fonctions que j'utilise sont les mêmes que celles de mon timer (MMTimer) et que j'ai développé sous XP.

    je vais regarder ça de plus près.

    Édition #1:

    Reste à vérifier le fonctionnement, mais ça passe tel quel au niveau de la compilation et de l’installation du paquet (bpl) en XP avec Codegear 2009.

    faut pas oublier d'inclure ws2_32.lib dans le package

Discussions similaires

  1. Comment connaitre la taille d'un packet UDP ?
    Par Djobird dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 16/07/2009, 16h58
  2. probleme de reception de message udp apres envoi
    Par zarbiman dans le forum Développement
    Réponses: 2
    Dernier message: 12/12/2007, 23h21
  3. Problème de packet UDP avec les routeurs
    Par Thixomag dans le forum Développement
    Réponses: 16
    Dernier message: 11/11/2007, 20h38
  4. Checksum d'un packet udp
    Par sebastien.mz dans le forum Réseau
    Réponses: 3
    Dernier message: 12/05/2007, 15h00
  5. récupérer la taille d'un packet UDP
    Par beLz dans le forum Réseau
    Réponses: 17
    Dernier message: 07/03/2007, 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