none
code couche application en C++ RRS feed

  • Question

  • bonjour, je travaille avec Visual C++ 2010. je suis entrain de développer une application qui se base sur le modèle TCP/IP en utilisant le protocole UDP dans la couche transport.

    j'ai implémenté les 3 couches MAC/IP/UDP capables de recevoir et envoyer les trames de et vers la couche physique.

    j'ai besoin d'un code ou une fonction qui assure le passage de la couche application vers la couche transport dans le cas d'émission de trame, et de la couche transport vers la couche application dans le cas de reception de trame.

    d'après mes connaissances la couche application appelle la fonction GetMessage(message,PortNbr) ou SendMessage(message,PortNbr) pour avoir le message mais je ne connais pas exactement le code qui vérifie la disponibilité du port puis envoi (ou reçoit) le message à travers.

    S'il vous plait, y a il quelqu'un peut m'aider?

    • Type modifié Ciprian Duduiala lundi 20 juin 2011 13:52 pas de solution trouvée ou acceptée
    • Type modifié Ciprian Duduiala jeudi 7 juillet 2011 14:27 solution trouvée
    lundi 13 juin 2011 20:17

Réponses

  • Don't panic ;-)

    On fait SIMPLE :

    Il faut distinguer l'émission et la réception

     

    En émission :

    Ton programme utilise la méthode envoyer_Message de ta couche transport. C'est la couche transport qui implémente envoyer_Message car le programme (en terme de couche) ne doit pas connaître le format UDP.

    envoyer_Message de ta couche transport utilise la méthode envoyer_Paquet de la couche réseau.

    envoyer_Paquet de la couche réseau utilise la méthode envoyer_Trame de ta couche liaison. Winpcap est ta couche physique.

    Chaque couche prend les données passées en paramètre par la couche supérieur, alloue un buffer un peu plus grand que les données passées pour pouvoir y mettre (dans le buffer) les en-têtes de la couche et y copier le contenu des données passées en paramètre juste après ces en-têtes. Une fois ce buffer contenant les données utiles pour le protocole de ce niveau de la pile, vous appelez la fonction envoyer_XXX de la couche inférieur.

    Dans la couche liaison, vous n'avez qu'à habiller le paquet IP fourni par la couche supérieur avec les en-têtes Ethernet et l'envoyer aux fonctions de Winpcap.

     

     

    En réception, c'est différent :

    Votre programme appel une méthode enregistrer_canalMessage de la couche transport, en passant tous les paramètres nécessaires au filtrage par la couche inférieur (port UDP de la destination, mais aussi optionnellement, le port UDP de la source, l'adresse IP de la source et l'adresse IP de la destination (pour les machines avec plusieurs adresses IP). Avec ces paramètres, il y aura aussi les informations sur comment notifier le programme en cas de réception en cas de message UDP respectant les paramètres données (Event ou fonction de callback).

    La couche transport enregistre les informations tel que le port UDP à écouter et le canal de notification au programme. Elle appel ensuite enregistrer_canalPacket de la couche réseau avec les informations nécessaires au filtrage par le couche réseau, les éventuelles adresses IP sources et destinations.

    Et ainsi de suite jusqu'à la couche liaison qui appelera les fonctions de filtrage de Winpcap, mais c'est pas une obligation. La couche liaison pourra tout recevoir mais ne notifier à la couche supérieure que les messages correspondant aux paramètres passées à la méthode enregistrer_canalTrame de cette couche.

    Il reste l'implémentation dans chaque couche de la méthode qui sera notifié par la couche inférieure. Elle récupèrera les données, les en-tête utilisés par les couches inférieures ne font pas partie de ces données. Chaque couche est responsable de faire passer par le canal de communication que les informations nécessaires, elle supprime donc les en-têtes qu'elle a ajoutée à l'émission des données. En réception, la couche utilisera ses en-tête pour connaitre le ou les canaux de notification correspondants aux données reçus et les notifient avec les données sans ces en-tête.

    La méthode du programme à l'écoute du canal de notification passé à la couche transport ne recevra donc que les données correspondants aux restrictions données par les paramètres passés à la méthode enregistrer_canalMessage, et les données qu'elle recevra seront clean, sans aucuns des en-têtes ajouté par les couches intermédiaires à l'émission car ils ont été supprimés par la même couche lors de la réception.

    Cosmos

    http://cosmos.codeplex.com/SourceControl/changeset/view/71406

     

    eEx Network Library

    http://eex.codeplex.com/SourceControl/changeset/view/5877


    Paul Bacelar, Ex - MVP VC++
    vendredi 1 juillet 2011 13:07
    Modérateur

Toutes les réponses

  • Utilisez-vous toujours les fonctions WinPCap ?

    Avez-vous vous même construit les fonctions GetMessage et SendMessage ? Utilisez-vous des sockets ?


    Delphine GARRO
    mardi 14 juin 2011 13:37
  • N'utilisez pas les messages Windows pour les communications asynchrones (appel de la couche basse quand un message arrive).

    Le seul avantage de cet approche est une gestion simplifier du multi-threading mais cela oblige à avoir des fenêtres, même pour une application console. Beurk !

    Utilisez plutôt le concept de io completion port.

    http://www.codeproject.com/KB/IP/SimpleIOCPApp.aspx

     

    http://tangentsoft.net/wskfaq/articles/io-strategies.html


    Paul Bacelar, Ex - MVP VC++
    mardi 14 juin 2011 15:40
    Modérateur
  • merci beaucoup, je vais voir les I/O completion ports puisque j'ai besoin des Queuing Ports pour accéder à la couche application à partir de la couche transport (ou le contraire). je vous mettrai au courant :)

    j'utilise toujours winpcap, cette partie est une continuité de mon travail que nous avons déjà discuté. merci pour votre aide. 

    vendredi 17 juin 2011 19:42
  • je pense que même avec les I/O completion ports,je dois utiliser les sockets ce que je ne préfère pas le faire. je veux surtout coder une couche application ou une API user qui a une seule instance et qui gère l'envoi et la réception des messages à travers un port UDP.

    j'ai vu quelques codes sur net où il y a get instance(), start() ou config() et meme des fonctions de création et d'écriture dans les ports, mais ils sont tellement compliqués et reliés à plusieurs fichiers headers que je n'ai pas pu m'en servir.

    est ce que vous avez un code simple qui peut m'aider.j'ai pas besoin de coder une couche application très compliquée mais seulement qui se charge de l'envoi et la réception à travers un ports UDP et qui retourne une seule instance.

     

    D'autre part, permettez moi de poser une deuxième question. je cherche également un bout de code qui fait la fragmentation IP en émission et la défragmentation IP en réception. est ce que vous pouvez m'aider?

    Merci pour tout ce que vous faites pour moi,Delphine et Paul. ça fait chaud au cœur de trouver l'aide d'une personne d'un autre bout de ligne sans se connaitre d'avance.

    j'ai pratiquement terminé mon application mais il me reste ces petits détails importants à régler.

    j'ai également presque fini la rédaction de mon rapport de projet et je vais le déposer la semaine prochaine avec l'application.

    Merci d'avance :)

    samedi 18 juin 2011 23:09
  • Les IO completion port ne sont pas liés au socket mais à la notion de handler. Cela peut être des sockets mais aussi des fichiers, des Events et tout autres type d'objets 'Kernel'.

    Normalement, votre type de fonctionnalité devrait se faire sous la forme d'un driver Kernel qui devrait s'intégrer dans la stack IP de Windows.

    Vos applications consommatrice utiliseraient le nouveau protocole UDP standard, le couche IP standard et elle utiliserait votre driver Kernel pour les problématiques de niveau liaison.

    Cela est possible si votre protocole est bien de type liaison (Ethernet like).

    Mais on ne va pas revenir en arrière.

     

    Pour vous aider, il nous faudrait avoir comment Winpcap vous notifie, de manière asynchrone, l'arrivé de données. Je ne suis pas un spécialiste Winpcap.

    Je vois deux grands modes de notification, la fourniture d'une fonction de callback (performant mais complexe à mettre en place avec les problématiques de threading) et la notification d'event (IO completion port en est une forme dérivée).

    La notification par message n'est qu'une version bridée du mode notification par Event.

    Ces modes de notification sont de bas niveau et peuvent être encapsulés dans des objets. La description que vous donnez est le Design Pattern Singleton.

    C'est tout à fait faisable mais c'est une encapsulation de "haut" niveau et je doute qu'une librairie "système" comme Winpcap fournisse un telle niveau d'abstraction.

    Il faut donc connaître de mode de notification de Winpcap et l'encapsuler dans un Singleton.

    Vous devez concevoir comment le Singleton fournirra ses services. Vous devez déterminer si c'est lui qui gérera la bufferisation de message et comment il notifie ces clients etc...

    Je pense que les exemples que vous trouverez sur le net correspondent aux implémentations de ce Design Pattern ou un autre car il faut un haut niveau d'abstraction pour avoir une API conviviale.

     

    Pour une implémentation de la fragmentation IP en émission et la défragmentation IP en réception, je regarderais du côté du code source des différents OS.

    Une stack IP est un "must have" de tout OS moderne.

    Donc je regarderais du côté de code source de Linux ou les implémentations comme Cosmos (http://cosmos.codeplex.com/) ou les librairies comme eEx Network Library (http://eex.codeplex.com/).

    Le C# est assez proche du C++ ;-).


    Paul Bacelar, Ex - MVP VC++
    mercredi 22 juin 2011 09:08
    Modérateur
  • Salut Paul,

    Merci pour toutes ces informations, vous savez, le temps me presse beaucoup, je ne pense pas que j'aurai suffisamment  de temps pour chercher à propos des APIs malgré que c'est ce que j'ai souhaité au début mais vu que je suis limitée par une date de dépôt de l'application et du rapport, je pensais à utiliser les I/O completion ports si vous pensez que c'est facile à implémenter. ça me suffit largement d'avoir une couche application qui se base sur les handlers pour envoyer et recevoir des messages à travers un port UDP sans être un singleton ou d'un haut niveau d'abstraction.

    Mon application jusqu'à maintenant s'arrête au niveau de la couche transport, c pour cette raison que je dois implémenter la couche application pour avoir une pile complète, ce qui est recommandé.

    à propos cette couche est standard et conforme avec les piles standards d'Ethernet, elle n'est pas reliée aux spécifications de mon protocole.

    Est-ce que vous avez s'il vous plait un petit bout de code qui peut me servir :( je suis vraiment très pressée par le temps.votre aide est très précieuse.

     

    merci beaucoup

    jeudi 23 juin 2011 20:40
  • Quel est le mode de notification de votre couche transport : fonction de callback, handle évènements, envoie de message, autre ?

    L'implémentation de la couche application est plus dépendante de l'API de la couche transport que de l'API qu'elle publie pour les applications.

    L'implémentation sommaire d'un singleton prend quelques minutes, mais il faut connaître le mode de notification de la couche transport pour l'implémenter dans notre cas d'utilisation.

    Postez un projet avec une implémentation de votre couche transport vide mais ayant la même API que cotre couche transport opérationnel.

    Nous pourrons rapidement ensuite proposer une implémentation d'une couche applicative avec une API conviviale pour le programmeur applicatif.


    Paul Bacelar, Ex - MVP VC++
    vendredi 24 juin 2011 08:40
    Modérateur
  • Salut Paul,

     

    voici une partie de mon programme principal de l'émetteur. Puisque je travaille en mode console, j'affiche:

    cout << "Entrer User data "<<endl<<endl;


    cin >> Message; 


    unsigned int TailleMessage=strlen(Message);

     

    unsigned int Taille_PaquetUDP=TailleMessage+8; 

    // j'alloue la case mémoire pour le paquet UDP

    unsigned char *PaquetUDP=new unsigned char[Taille_PaquetUDP]; 

    // puis j'appelle la fonction de la classe "CoucheTransportTx" pour remplir l'entête UDP afin de //construire le paquet

    UDPlayerTx.Construire_Paquet_UDP(UDPDestinationPort,UDPSourcePort,PaquetUDP,Taille_PaquetUDP,Message,TailleMessage);

     

    //Dans la classe "coucheTransportTx", voici la fonction qui construit le paquet UDP

     

    CoucheTransportTx::Construire_Paquet_UDP(unsigned short UDPportdst,
                                                  unsigned short UDPportsrc,
                                                  unsigned char* PaquetUDP,
                                                  unsigned int Taille_PaquetUDP,
                                                  char *Message,
                                                  unsigned int Taille_Message)

     

    //Cette fonction construit le paquet UDP à l'aide de la fonction memcpy

     

    unsigned short Temp1=htons(UDPportsrc);

    memcpy((void*)PaquetUDP,(void*)&Temp1,2);    //port source UDP, 2 octets


    u_short Temp=htons(UDPportdst);


    memcpy((void*)(PaquetUDP+2),(void*)&Temp,2);    //port destination UDP, 2 octets


    unsigned short longueurUDP=htons(Taille_PaquetUDP);

     

    memcpy((void*)(PaquetUDP+4),(void*)&longueurUDP,2);  //la longueur du paquet

    UDP=Message+enteteUDP


      // Appel à la fonction de checksumUDP


    unsigned short ChecksumUDP=htons(CalculChecksumUDP(Taille_PaquetUDP));


    memcpy((void*)(PaquetUDP+6),(void*)&ChecksumUDP,2);


    memcpy((void*)(PaquetUDP+8),(void*)Message,Taille_Message);      

     

    // par la suite l'appel à la fonction de la classe "CoucheReseauTx" qui construit le paquet IP de la //même manière que le paquet UDP, j'ai fait cet appel à partir du programme principal mais je //peux le faire également à partir de la classe "CoucheTransportTx" 

     

    En réception, les appels de fonctions se font d'une classe à l'autre et pas à partir du programme principal comme en émission. En Effet,  j'ai appelé la fonction de la classe "CoucheTransportRx" à partir de la classe "CoucheReseauRx" comme suit:

    UDPlayer.Reception_Paquet_UDP(Paquet_UDP,LongueurUDP);

     

    // Dans la classe "CoucheTransportRx", voici la fonction de réception du paquet

     

     CoucheTransportRx::Reception_Paquet_UDP(u_char * Paquet_UDP,u_int LongueurUDP)


    {


      UDPhdr=(struct EnteteUDP*)Paquet_UDP;


      Port_Source=ntohs(UDPhdr->UDPportSrc);


      Port_Destination=ntohs(UDPhdr->UDPportDest);


      longueur=ntohs(UDPhdr->UDPlength);


      checksum=ntohs(UDPhdr->UDPchecksum); 

    }

     

    Et finalement, dans la couche transport aussi, j'affiche le message que j'ai envoyé de l'émetteur comme suit

     

    u_int LongueurMessage=LongueurUDP-8;


    u_char *Message=Paquet_UDP+8;


    Message[LongueurMessage]=0x00;


    printf("Le message est:             %s\n  ",Message);            

    // Voilà donc la couche Transport dans l'application émettrice et l'application réceptrice, le message s'affiche dans la couche transport puisque je manque de la couche application.

     

    J'espère que cela peut vous servir pour pouvoir m'aider. je vous remercie infiniment Paul.

     

    vendredi 24 juin 2011 13:29
  • Salut Paul,

    Salut Sloumanaw ;-)

    Désolé pour le manque de réactivité, je suis un peu pris actuellement.

    unsigned int Taille_PaquetUDP=TailleMessage+8; 

    // j'alloue la case mémoire pour le paquet UDP

    Les couches supérieurs de doivent pas connaître ces détails. Soit vous passez les données dans un buffer correspondant à la taille des données bruts et des en-têtes et suffixe du protocole. Dans ce cas "Construire_Paquet_UDP" devrait être remplacé par un simple "SendMessage" qui prendre en paramètre Message et TailleMessage mais pas PaquetUDP ou Taille_PaquetUDP.

    Le buffer sera alloué par la couche inférieure car c'est la seul à devoir connaître le format de ses en-têtes. En plus, c'est elle qui saura quand désallouer ces buffers en cas d'appel asynchrones. C'est l'approche académique.

     

    Soit vous implémentez dans la couche inférieure une fonction d'allocation des buffers. Cela permet d'éviter des allocations cascades. Mais la couche supérieur n'indique que la taille qui lui est nécessaires. La couche inférieur allouera un buffer un peu plus grand et donnera un pointeur décalé par rapport au début du buffer alloué, correspondant à la taille des en-têtes de la couche inférieure.

    Le raisonnement est le même en multi-couche, chaque fonction d'allocation utilise la fonction d'allocation de la couche du dessous. Chaque couche ne connaît que la taille des en-têtes qu'il gère et pas celles des couches inférieures.

    La gestion des allocations est plus problématique mais en utilisant des bibliothèques d'allocation évoluées cela est facilement gérable.

    //Dans la classe "coucheTransportTx", voici la fonction qui construit le paquet UDP

     

    CoucheTransportTx::Construire_Paquet_UDP(unsigned short UDPportdst,
                                                  unsigned short UDPportsrc,
                                                  unsigned char* PaquetUDP,
                                                  unsigned int Taille_PaquetUDP,
                                                  char *Message,
                                                  unsigned int Taille_Message)

     

    Même remarques.

    En réception, les appels de fonctions se font d'une classe à l'autre et pas à partir du programme principal comme en émission. En Effet,  j'ai appelé la fonction de la classe "CoucheTransportRx" à partir de la classe "CoucheReseauRx" comme suit:

    Là, c'est une gros entorse, voir une hérésie ;-).

     

    La couche inférieure ne doit pas connaître les couches supérieures.

     

    Mes remarques précédentes sur les différents modes de notification donnent des moyens pour casser cette dépendance.

    La couche supérieure peut utiliser une fonction de la couche inférieur pour enregistrer une des ses fonctions, donc dans la couche supérieure, mais la couche inférieur n'a pas de connaissance de la couche supérieure. C'est la couche supérieure qui utilise la couche inférieure (en "s'enregistrant").

     

    La couche inférieure peut passer un "Event" à la place d'un pointeur de fonction. La couche inférieure notifiera cet "Event" lors d'une réception. La couche supérieure devra réagir à cette notification. Mais dans ce cas aussi, la couche inférieure ne connait pas la couche supérieure.

     

    Il faut bien comprendre le principe d'une architecture en couche.

     

    Chaque couche ne doit connaître aucun des détails des couches inférieures, elles ne doivent connaître que l'API de la couche inférieure. On doit pouvoir changer les couches supérieures sans modifier les couches inférieures. On doit pouvoir changer les couches inférieures si la nouvelle couche inférieure implémente la même API. Comme chaque couche a un niveau d'abstraction standardisé, les API des implémentations des couches de même niveau sont naturellement les mêmes.


    Paul Bacelar, Ex - MVP VC++
    lundi 27 juin 2011 09:18
    Modérateur
  • Salut Paul,

     

    j'ai changé la structure de mon application. càd par exemple pour la fonction construire_paquetUDP je n'ai plus en entrée le paquet UDP et sa longueur mais plutot le message que l'utilisateur veut envoyé et sa longueur. Ainsi le passage d'une couche à l'autre se fait avec des appels de fonctions càd couche transport appel la couche réseau avec la fonction construire_paquetIP qui prend comme argument le paquetUDP et sa longueur et donne en sortie le paquetIP.

    En tout cas ça a marché, et honnêtement je n'ai plus le temps de faire d'autres changements, j'ai déjà donné l'application avec cette dernière version. mais je dois effectuer quelques tests pour le jour de la soutenance et j'ai toujours le problème de l'IP fragmentation.je cherche un petit bout de code de fragmentation et de défragmentation parce que je compte faire un test de fragmentation. d'autre part quand je fait un petit test de l'application, le recepteur est entrain de recevoir, en utilisant winpcap, tout type de trame qui circulent dans le réseau.Alors si je veux installer un filtre ou un truc pareil pour ne recevoir que les trames que j'envoie de mon émetteur, qu'est ce que je dois faire alors?

    Merci pour votre aide et soyez patient avec moi s'il vous plait, je n'ai pas d'autres personnes qui peuvent m'aider. merci beaucoup.

    je suis en attente de votre réponse. 

     

    jeudi 30 juin 2011 16:42
  • Le résumé de vos modifications me semble prometteur.

    Le truc, c'est que le nom "construire_paquetXXX" semble dire que le modèle d'utilisation est : J'appelle "xxx packet = construire_paquetXXX(message,...) puis l'appelle envoyer_paquetXXX(packet,...) .

    Moi, j'aurais fait qu'une seule fonction envoyer_messageXXX(message,...).

    Si vous n'avez qu'une fonction, alors c'est juste un problème de nomtage. Mais attention, le nommage correct des fonctions n'est pas une tâche à prendre à la légère.

    Pour la fragmentation IP, je vous ai donné des références sur des OS "virtuelle" qui devraient implémenter la stack IP donc le fragmentation IP, et comme c'est de l'Open Source, le code doit y être visible.

    Comme ce sont des projets de grandes tailles, s'ils sont de bonnes qualités, les dépendances avec d'autres composants doivent être gérable donc le code doit être transposable dans d'autres langages et d'autre OS.

    Si l'on reprend mon explication de comment implémenter le canal montant d'une stack de protocole, la couche supérieure enregistre un event ou une fonction de callback via une fonction d'enregistrement de la couche inférieure.

    Dans notre cas de figure, la couche de plus bas niveau va recevoir toutes les trames mais si personne ne c'est enregistré, elle n'en fera rien.

    Si la primitive d'enregistrement de la couche de plus bas niveau (niveau liaison) prend en paramètre ce qui distingue les différents protocoles de niveaux supérieurs. Je me rappel plus trop le format d'une trame Ethernet, mais je crois qu'il y a un numéro de protocole. Si c'est bien ça, la primitive d'enregistrement de la couche liaison prend en paramètre un numéro de protocole.

    Quand la couche liaison reçoit une trame, elle vérifie le numéro de protocole, vérifie que quelqu'un c'est bien enregistré pour ce numéro de protocole, et si c'est le cas, lance l'event ou appel la fonction de callback qui a été passé en paramètre de la primitive d'enregistrement.

    La couche réseau sera donc prévenue et vérifiera que l'adresse IP de la trame correspond, sinon, elle n'en fera rien.

    C'est le même principe d'enregistrement pour la couche réseau mais avec le type de protocole transport (UDP ou TCP) et le numéro de port en paramètre. Cette couche fera le dispatching des packets IP selon ces paramètres enregistrés vers la couche transport correspondante et en utilisant l'event ou la fonction de callback associé au numéro de port fourni lors de l'appel de la primitive d'enregistrement.

    Avec ce principe, la couche transport UDP ne recevra que les trame UDP et recevra un event ou passera par une fonction de callback spécifique par numéro de port.

    Le code des OS devrait vous montrer cette approche.


    Paul Bacelar, Ex - MVP VC++
    vendredi 1 juillet 2011 09:52
    Modérateur
  • Alors si j'ai bien compris, je dois remplacer la fonction construire_paquetUDP par envoyer_paquetUDP qui est une fonction de la couche transport mais qui sera appelé dans la couche IP: paquetUDP=envoyer_paquetUDP puis envoyer_paquetIP qui est une fonction de la couche réseau mais qui sera appelée dans la couche liaison de données. c ça?

    mais avant tout je dois faire une fonction envoyer_message(Message,TailleMessage) dans le programme principal (puisque j'ai pas de couche application) et qui sera appelé dans la couche transport, non?

    et en reception est ce que j'utilise la meme méthode de envoyer_paquetXXX ou je fais reception_trame qui capte les trames de la couche physique et qui prend en arguments la trame reçue et donne en sortie le paquet IP et reception_paquetIP qui sera appelé dans la couche liaison de données et qui prend en argument le paquet IP et donne le paquet UDP. c ça?

     

    vendredi 1 juillet 2011 11:27
  • concernant le filtrage de trames, je l'ai fais pour la couche réseau et la couche transport mais j'ai pas pu le faire pour la couche liaison de données car je dois disposer des fonctions winpcap qui peuvent faire ce filtrage entre la couche physique et la couche liaison de données. je ne sais pas s'il ya une autre fonction de filtrage sans utiliser winpcap dans la couche liaison de données.

    j'ai pas pu accéder au code source des projets dans les liens que vous m'avez donné je ne comprend rien!!  :'( je suis à bout de nerf :((((((((

    vendredi 1 juillet 2011 11:37
  • Don't panic ;-)

    On fait SIMPLE :

    Il faut distinguer l'émission et la réception

     

    En émission :

    Ton programme utilise la méthode envoyer_Message de ta couche transport. C'est la couche transport qui implémente envoyer_Message car le programme (en terme de couche) ne doit pas connaître le format UDP.

    envoyer_Message de ta couche transport utilise la méthode envoyer_Paquet de la couche réseau.

    envoyer_Paquet de la couche réseau utilise la méthode envoyer_Trame de ta couche liaison. Winpcap est ta couche physique.

    Chaque couche prend les données passées en paramètre par la couche supérieur, alloue un buffer un peu plus grand que les données passées pour pouvoir y mettre (dans le buffer) les en-têtes de la couche et y copier le contenu des données passées en paramètre juste après ces en-têtes. Une fois ce buffer contenant les données utiles pour le protocole de ce niveau de la pile, vous appelez la fonction envoyer_XXX de la couche inférieur.

    Dans la couche liaison, vous n'avez qu'à habiller le paquet IP fourni par la couche supérieur avec les en-têtes Ethernet et l'envoyer aux fonctions de Winpcap.

     

     

    En réception, c'est différent :

    Votre programme appel une méthode enregistrer_canalMessage de la couche transport, en passant tous les paramètres nécessaires au filtrage par la couche inférieur (port UDP de la destination, mais aussi optionnellement, le port UDP de la source, l'adresse IP de la source et l'adresse IP de la destination (pour les machines avec plusieurs adresses IP). Avec ces paramètres, il y aura aussi les informations sur comment notifier le programme en cas de réception en cas de message UDP respectant les paramètres données (Event ou fonction de callback).

    La couche transport enregistre les informations tel que le port UDP à écouter et le canal de notification au programme. Elle appel ensuite enregistrer_canalPacket de la couche réseau avec les informations nécessaires au filtrage par le couche réseau, les éventuelles adresses IP sources et destinations.

    Et ainsi de suite jusqu'à la couche liaison qui appelera les fonctions de filtrage de Winpcap, mais c'est pas une obligation. La couche liaison pourra tout recevoir mais ne notifier à la couche supérieure que les messages correspondant aux paramètres passées à la méthode enregistrer_canalTrame de cette couche.

    Il reste l'implémentation dans chaque couche de la méthode qui sera notifié par la couche inférieure. Elle récupèrera les données, les en-tête utilisés par les couches inférieures ne font pas partie de ces données. Chaque couche est responsable de faire passer par le canal de communication que les informations nécessaires, elle supprime donc les en-têtes qu'elle a ajoutée à l'émission des données. En réception, la couche utilisera ses en-tête pour connaitre le ou les canaux de notification correspondants aux données reçus et les notifient avec les données sans ces en-tête.

    La méthode du programme à l'écoute du canal de notification passé à la couche transport ne recevra donc que les données correspondants aux restrictions données par les paramètres passés à la méthode enregistrer_canalMessage, et les données qu'elle recevra seront clean, sans aucuns des en-têtes ajouté par les couches intermédiaires à l'émission car ils ont été supprimés par la même couche lors de la réception.

    Cosmos

    http://cosmos.codeplex.com/SourceControl/changeset/view/71406

     

    eEx Network Library

    http://eex.codeplex.com/SourceControl/changeset/view/5877


    Paul Bacelar, Ex - MVP VC++
    vendredi 1 juillet 2011 13:07
    Modérateur
  • merciii Paul pour toute ces explication, j'ai changé les nom des méthodes en émission car ça ne manque que ça, je l'ai implémentée de la manière que vous m'avez expliqué.

    En réception, la méthode de communication que vous m'avez proposé est très intéressante mais pour mon cas je veux que le filtrage s'effectue avant de passer à la couche liaison de données càd au niveau de l'API de winpcap alors j'ai cherché dans les fonctions de winpcap, j'ai trouvé une méthode de filtrage je suis entrain de voir comment l'adapter au contexte de mon protocole.

    merci beaucoup pour les liens, pour votre patience, pour votre temps. j'espère que la vie vous apportera toujours des amis et des gens pour vous aider comme vous l'avez fait avec moi.

     

    à la prochaine incha 'allah :)

    dimanche 3 juillet 2011 21:18