begin process at 2008 05 16 06:00:33
1 173 216 membres
58 nouveaux aujourd'hui
13 970 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

LES SOCKETS C++ COMME DS MIRC : TOUT EST SIMPLE AVEC LA CLASSE PROSOCK


Information sur la source

Catégorie :Réseaux & Internet Niveau : Débutant Date de création : 18/02/2004 Date de mise à jour : 18/02/2004 19:56:00 Vu / téléchargé: 4 855 / 606

Note :
10 / 10 - par 4 personnes
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (14)
Ajouter un commentaire et/ou une note


Description

voila j'ai essayé de faire une classe pour rendre l'utilisation des sockets en c++ aussi simple que ce qu'on peut faire avec mirc. vous reconnaitrez donc des trucs qui vous sont familiers genre ON_SOCKREAD, ON_SOCKCLOSE etc...
pour utiliser la classe, il faut deux choses : une fonction void (ProSock*,int) qui va etre chargée d'intercepter les notifications, et un objet de type ProSocket que vous avez initialisé en faisant CreateProSocket(lenomdevotrefonction). cf les exemples de client et serveur telnet pour comprendre ca.
Meme s'il existe un constructeur sans parametre, vous devez toujours pour un seul ProSock utiliser le constructeur avec paramètres pour indiquer le nom de la fonction qui va intercepter les notifications. Sinon elles seront bien envoyées, mais comme personne ne va les intercepter, elles seront perdues.
Pour déclarer un tableau de ProSock qui vont tous utiliser la meme fonction SimpleProc, faites : ProSock::pDefaultFunc = SimpleProc ; ProSock tableau[5];    la premiere instruction permet de mettre la fonction par défaut de la classe à SimpleProc, et c'est cette fonction qui est utilisée par le constructeur sans paramètres.
Tout ca fonctionne un peu comme la fonction DialogBox dont le dernier paramètre est le nom de la fonction qui est censée intercepter les notifications de Windows.
Pour changer le nom de la fonction associée à un ProSocket (celle à qui sont envoyées les notifications), utilisez la méthode SetNewProc(SOCKFUNCT f) de la classe.
J'ai commenté le .h donc lisez le pour connaitre les différentes fonctions et notifications.

Pour utiliser cette classe ds un de vos projets, 2 possibilités : vous mettez ProSock.cpp et ProSock.h dans votre projet, et ds ProSock.h vous enlevez la ligne '#pragma comment(lib,"ProSock.lib")'. Ou bien vous mettez ProSock.lib avec les autres .lib de base (votre compilateur a bien un répertoire lib, sinon mettez le ds le répertoire courant de votre projet), et vous ajoutez juste ProSock.h
Dans visualc++, pour naviguer entre les différents projets, clic droit : Set As Active Project. Ca compile que le projet par défaut donc bon...

Source

  • /////////////////////////////////
  • // Code d'un client telnet ////
  • /////////////////////////////////
  • #include <stdio.h>
  • #include "../ProSock.h"
  • bool sortie = false;
  • void ClientProc(ProSock* s, int message)
  • {
  • switch(message)
  • {
  • case ON_SOCKREADLN:
  • {
  • char text[500];
  • s->SockReadln(text,sizeof(text));
  • printf("Serveur: %s\n",text);
  • break;
  • }
  • case SOCKREAD_ERROR:
  • {
  • printf("Erreur lors de la lecture, le socket va etre ferme automatiquement...\n");
  • break;
  • }
  • case ON_SOCKCLOSE:
  • {
  • printf("Le serveur a ete deconnecte\n");
  • sortie = true;
  • break;
  • }
  • case ON_SOCKOPEN:
  • {
  • printf("Vous vous etes connectes avec succes sur %s (port %d)\n",s->Ip(),s->Port());
  • break;
  • }
  • case SOCKOPEN_ERROR:
  • {
  • printf("Connection sur %s (port %d) impossible\n",s->Ip(),s->Port());
  • break;
  • }
  • case SOCKWRITE_ERROR:
  • {
  • printf("Erreur lors du write\n");
  • break;
  • }
  • }
  • }
  • int main()
  • {
  • ProSock ClientTelnet = CreateProSocket(ClientProc);
  • ClientTelnet.SockOpen("127.0.0.1",23);
  • while(true)
  • {
  • char chaine[256];
  • int c = 0;
  • do
  • {
  • chaine[c++] = getc(stdin);
  • chaine[c] = '\0';
  • if (!strcmp(chaine,"exit"))
  • {
  • ClientTelnet.SockClose();
  • goto end;
  • }
  • } while (chaine[c-1] != '\n');
  • if (sortie) break;
  • ClientTelnet.SockWrite(chaine);
  • }
  • end:
  • system("PAUSE");
  • return 0;
  • }
  • /////////////////////////////////
  • // Code d'un server telnet ////
  • /////////////////////////////////
  • #include <stdio.h>
  • #include "../ProSock.h"
  • void ServerProc(ProSock* s, int message);
  • void ListenProc(ProSock*s, int message);
  • ProSock SAccept = CreateProSocket(ServerProc);
  • ProSock SListen = CreateProSocket(ListenProc);
  • bool AcceptationOk = false;
  • bool sortie = false;
  • void ListenProc(ProSock*s, int message)
  • {
  • switch(message)
  • {
  • case ON_SOCKLISTEN:
  • {
  • printf("Un client est arrive\n");
  • s->SockAccept(&SAccept);
  • // On peut choisir ou nom de fermer une fois que quelqu'un s'est connecté
  • s->SockClose();
  • break;
  • }
  • case SOCKLISTEN_ERROR:
  • {
  • printf("Impossible d'ecouter le port %d\n",s->Port());
  • sortie = true;
  • break;
  • }
  • }
  • }
  • void ServerProc(ProSock* s, int message)
  • {
  • switch(message)
  • {
  • case ON_SOCKACCEPT:
  • {
  • printf("Connection acceptee\n");
  • AcceptationOk = true;
  • break;
  • }
  • case ON_SOCKREADLN:
  • {
  • char text[256];
  • s->SockReadln(text,sizeof(text));
  • printf("Client: %s\n",text);
  • break;
  • }
  • case SOCKREAD_ERROR:
  • {
  • printf("erreur lors de la lecture\n");
  • break;
  • }
  • case ON_SOCKCLOSE:
  • {
  • printf("Fermeture du socket : le client s'est deconnecte\n");
  • sortie = true;
  • break;
  • }
  • }
  • }
  • int main(int argc, char* argv[])
  • {
  • SListen.SockListen(23);
  • // On attent qu'une connection ait été etablie pour pouvoir envoyer des trucs.
  • while (true)
  • {
  • if (AcceptationOk || sortie)
  • break;
  • Sleep(200);
  • }
  • while (true)
  • {
  • char chaine[256];
  • int c = 0;
  • do
  • {
  • chaine[c++] = getc(stdin);
  • chaine[c] = '\0';
  • if (!strcmp(chaine,"exit"))
  • {
  • SAccept.SockClose();
  • goto end;
  • }
  • } while (chaine[c-1] != '\n');
  • if (sortie) break;
  • SAccept.SockWrite(chaine);
  • }
  • end:
  • system("PAUSE");
  • return 0;
  • }
/////////////////////////////////
// Code  d'un client telnet  ////
/////////////////////////////////



#include <stdio.h>
#include "../ProSock.h"

bool sortie = false;

void ClientProc(ProSock* s, int message)
{
   switch(message)
   {
      case ON_SOCKREADLN:
      {
         char text[500];
         s->SockReadln(text,sizeof(text));
         printf("Serveur: %s\n",text);
         break;
      }
      case SOCKREAD_ERROR:
      {
         printf("Erreur lors de la lecture, le socket va etre ferme automatiquement...\n");
         break;
      }
      case ON_SOCKCLOSE:
      {
         printf("Le serveur a ete deconnecte\n");
         sortie = true;
         break;

      }
      case ON_SOCKOPEN:
      {
         printf("Vous vous etes connectes avec succes sur %s (port %d)\n",s->Ip(),s->Port());
         break;
      }
      case SOCKOPEN_ERROR:
      {
         printf("Connection sur %s (port %d) impossible\n",s->Ip(),s->Port());
         break;
      }
      case SOCKWRITE_ERROR:
      {
         printf("Erreur lors du write\n");
         break;
      }
   }
}



int main()
{

   ProSock ClientTelnet = CreateProSocket(ClientProc);

   ClientTelnet.SockOpen("127.0.0.1",23);

    while(true) 
    {
        char chaine[256];
        int c = 0;
        do
        {
            chaine[c++] = getc(stdin);
            chaine[c] = '\0';
            if (!strcmp(chaine,"exit"))
            {
                ClientTelnet.SockClose();
                goto end;
            }

        } while (chaine[c-1] != '\n');
        if (sortie) break;
        ClientTelnet.SockWrite(chaine);
    }
end:
    system("PAUSE");
    return 0;
}

/////////////////////////////////
// Code  d'un server telnet  ////
/////////////////////////////////

#include <stdio.h>
#include "../ProSock.h"

void ServerProc(ProSock* s, int message);
void ListenProc(ProSock*s, int message);

ProSock SAccept = CreateProSocket(ServerProc);
ProSock SListen = CreateProSocket(ListenProc);

bool AcceptationOk = false;

bool sortie = false;
 

void ListenProc(ProSock*s, int message)
{
   switch(message)
   {
      case ON_SOCKLISTEN:
      {
         printf("Un client est arrive\n");
         s->SockAccept(&SAccept);
         // On peut choisir ou nom de fermer une fois que quelqu'un s'est connecté
         s->SockClose(); 


         break;
      }
      case SOCKLISTEN_ERROR:
      {
         printf("Impossible d'ecouter le port %d\n",s->Port());
         sortie = true;
         break;
      }
   }
}

void ServerProc(ProSock* s, int message)
{

   switch(message)
   {
      case ON_SOCKACCEPT:
      {
         printf("Connection acceptee\n");
         AcceptationOk = true;
         break;
      }
      case ON_SOCKREADLN:
      {
         char text[256];
         s->SockReadln(text,sizeof(text));

         printf("Client: %s\n",text);
         break;
      }
      case SOCKREAD_ERROR:
      {
         printf("erreur lors de la lecture\n");
         break;
      }

      case ON_SOCKCLOSE:
      {
         printf("Fermeture du socket : le client s'est deconnecte\n");
         sortie = true;
         break;
      }
   }
}


int main(int argc, char* argv[])
{
   SListen.SockListen(23);

   // On attent qu'une connection ait été etablie pour pouvoir envoyer des trucs.
   while (true)
   {
      if (AcceptationOk || sortie)
         break;
      Sleep(200);
   }
   while (true)
   {
      char chaine[256];
      int c = 0;
      do
      {
          chaine[c++] = getc(stdin);
          chaine[c] = '\0';
          if (!strcmp(chaine,"exit"))
          {
             SAccept.SockClose();
             goto end;
          }

      } while (chaine[c-1] != '\n');
      if (sortie) break;
      SAccept.SockWrite(chaine);
   }
end:
   system("PAUSE");
   return 0;
}

Conclusion

Les notifications :
ON_SOCKOPEN : qd on a réussi a se connecter apres une commande SockOpen.
SOCKOPEN_ERROR : la connection a échoué. Le socket va être automatiquement fermé.
ON_SOCKREAD : qd des données viennent d'etre lues sur le socket. On y accede avec SockRead.
ON_SOCKREADLN : qd une ligne vient d'etre lue sur le socket, grace a eventuellement plusieurs recv. On accède a la ligne avec SockReadln (les \r et \n on été enlevés).
SOCKREAD_ERROR : erreur lors de la lecture, peut etre qu'a l'autre bout on s'est déconnecté. Le socket va être automatiquement fermé.
ON_SOCKWRITE : des données ont été correctement envoyées.
SOCKWRITE_ERROR : erreur lors de l'envoi de données. Le socket n'est pas fermé tout seul, a vous de le faire si vous voulez avec SockClose.
ON_SOCKLISTEN : votre socket qui écoutait, vient de se rendre compte que quelqu'un veut se connecter. Il faut accepter la connection avec SockAccept(ProSock* unsocketpourlegarsquiveutseconnecter), sinon le socket est fermé.
SOCKLISTEN_ERROR : erreur lors de l'écoute. ex: si le port d'écoute est déja pris par une autre application.
ON_SOCKACCEPT : l'acceptation aprés le ON_SOCKLISTEN a réussi. Le socket est bien connecté à la personne qui était arrivée.
SOCKACCEPT_ERROR : l'acceptation a échoué.
ON_SOCKCLOSE : le socket a été fermé par un SockClose de votre part, ou bien il a été fermé automatiquement par une méthode de la classe.
SOCKET_ALREADY_USED : si vous essayez de faire par exemple 2 SockConnect de suite avec le meme socket (et que le premier avait réussi...)
Vous pouvez utilisez les methodes Ip() et Port() pour connaitre les ip et port de la connection distante.
Vous pouvez marquer le socket avec SockMark comme ds mIRC. Ya également un champ State qui peut servir de marque entière, ca peut etre utile ds certains cas.
Au fait, les sockets crées vont utiliser TCP...

Merci de signaler les éventuels bugs que vous trouverez, yen reste surement.
Un bug qui n'en est pas un : un oubli de break ds un case, ds votre fonction qui intercepte les notifications.
Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

  • signaler à un administrateur
    Commentaire de cosmobob le 18/02/2004 16:59:24

    n'hésitez pas à faire pleins de remarques, positives ou negatives!

  • signaler à un administrateur
    Commentaire de Cyberboy2054 le 18/02/2004 23:27:25

    Super =D
    Le code est bien commenté, bien architecturé .... Ca va me servir, c est clair.
    Le seul bémol -&gt; ca marche que sous windows :/
    Enfin bon, ca peut donner des idées pour un portage éventuel vers d autres librairies ...

  • signaler à un administrateur
    Commentaire de cosmobob le 18/02/2004 23:30:13

    ué ca marche ke sur windows pour une raison : jsais pas trop comment on fait des thread et des events sur unix. meme si c'est pas compliké, vu kjpeu pas tester... voila koi ! :p

  • signaler à un administrateur
    Commentaire de BlackGoddess le 20/02/2004 01:52:28

    un autre bémol =&gt; c'est un mélange complet entre le C et le C++ :p

    s-&gt;SockAccept(&SAccept); =&gt; c'est du C++
    strcmp(chaine,"exit") =&gt; c'est du C (en C++ on utilise les std::string
    printf("Un client est arrive\n"); =&gt; c'est du C (std::cout &lt;&lt; "Un client est arrive\n"; en c++)

    etc ...

  • signaler à un administrateur
    Commentaire de cosmobob le 20/02/2004 12:24:41

    et ? jvois pas trop ou est l'problème... une classe sur les sockets de toutes maniere, a partir du moment ou classe c'est du c++ et que les sockets c'est du c bon...

  • signaler à un administrateur
    Commentaire de cosmobob le 20/02/2004 12:29:25

    en+ la c'et l'exemple du serveur ou client telnet ou tu dis ca, c'est pas ce qui a ds la classe... tout ce qui est c marche encore en c++, l'inverse est faux. la c'est une classe, donc de toutes manieres ca tient pas en c pur... voila !! :p pour autant est ce qu'on doit rien utiliser des anciennes librairies du c ? chacun fait comme il veut...

  • signaler à un administrateur
    Commentaire de lepins le 19/04/2004 17:45:36

    Bonjour tout le monde,

    je suis etudiant et j'aimerai travailler sur ce code mais seulement je n'arrive pas à le modifier pour pouvoir utiliser plusieurs clients.
    En fait, je ne sais pas comment faire car les classes c'est un mystère pour moi.
    En effet, je voudrais pouvoir avoir un serveur et deux ou trois clients.
    Donc si quelqu'un pourrait m'aider cela serait sympa.

    Merci

  • signaler à un administrateur
    Commentaire de cosmobob le 25/04/2004 13:19:23

    il suffit de ne pas fermer le socket qui ecoute au moment ou quelqu'un se conecte (mais d'incrémenter un compteur qui est une variable globale par exemple).
    tu mets ca au début du code du serveur en remplacement de 'ProSock SAccept = CreateProSocket(ServerProc);'

    int compteur = 1;
    ProSock SAccept1 = CreateProSocket(ServerProc);
    ProSock SAccept2 = CreateProSocket(ServerProc);
    ProSock SAccept3 = CreateProSocket(ServerProc);

    et dans ListenProc tu mets :

            case ON_SOCKLISTEN:
            {
             printf("Un client est arrive\n");
             if (compteur == 1)
                s-&gt;SockAccept(&SAccept1);
             else if (compteur == 2)
                s-&gt;SockAccept(&SAccept2);
             if (compteur == 3)
                s-&gt;SockAccept(&SAccept3);
             compteur++;
             // On peut choisir ou nom de fermer une fois que quelqu'un s'est connecté
             // s-&gt;SockClose(); on ne le ferme plus...
             break;
            }


    il faut encore adapter le code pour que quand un client se déconecte, on décremente compteur, et qu'on puisse a nouveau utiliser le bon SAccept. Mais bon ca ce n'est plus tellement de l'utilisation de la classe, c'est de la prog plus générale....

    voir aussi la remarque sur la maniere de créer un tableau de prosocket. possibilité également d'utiliser le champ State de la classe, pour voir si un proSocket est toujours en train d'etre utilisé. (a vous de le changer aux bons moments)
    a++ ;p

  • signaler à un administrateur
    Commentaire de CptLuthor le 08/11/2004 15:52:31

    salut
    Moi je voudrai réaliser un client et un server VPN le plus simple possible, c a d je lance le server (un .exe tout petit) , mes pots lancent chacun le client ( un .exe tout petit )  et hop  on est connecté à distance et on se voit sur le réseau.

    je précise je ne ve pas de service de messagerie, c a d je ve juste quon se voi en reseau comme ca on se voit dans les jeux comme si on été en reseau local.

    voila merci à ce qui pourront maider

  • signaler à un administrateur
    Commentaire de cosmobob le 31/05/2005 08:26:42

    salut,
    dsl de répondre 10ans apres.
    si tu veux faire un truc pareil, faut que tu connaisses precisement le protocole utilisé par un vpn (qui se base peut etre aussi en partie sur des sockets udp tiens)
    A mon avis c'est pas évident, mais c'est en tout cas pas le sujet de cette source, meme si elle peut te simplifier legerement les choses qd tu en seras a la partie purement socket...

  • signaler à un administrateur
    Commentaire de Hades53 le 27/06/2005 01:13:17

    Vraiment très très bien !

    Effectivement, ça rend les socket beaucoup plus simples :)
    10/10

  • signaler à un administrateur
    Commentaire de SnOOpss le 24/06/2006 12:52:44

    Salut, d'abord bravo pour cette classe, c'est effectivement un jeu d 'enfant avec elle mais j'aurais 2 petites questions.
    Est qu'on est sur que l'autre personne a bien recu les messages envoyés ou il vaut mieux que le client reponde au serveur qu'il a bien recu les commandes ? En fait je l'utilise dans un jeu en reseau et le serveur envoi des infos au client et tant que le client ne recoit pas ces infos il bloque, si les données se perdent c'est foutu (en UDP par exemple le serveur envoi des paquets mais se fout de savoir si ils sont recus).
    Pour "nettoyer" les connections est ce que sockclose suffit ? En fait je lance l'appli en mode serveur puis 5 min apres je la relance en mode client sans rien redemarrer juste en faisant un sockclose puis de nouveau SockPrinc = CreateProSocket(ServerProc);

  • signaler à un administrateur
    Commentaire de SOAD08 le 14/09/2006 18:13:53

    Je dois etre le seul a avoir des problemes.... j'ai une magnifique linker error quelqu'un sait d'ou ça peut venir?

  • signaler à un administrateur
    Commentaire de SnOOpss le 14/09/2006 18:49:02

    c'est quoi ton message d'erreur ?

Ajouter un commentaire

Appels d'offres

Pub



CalendriCode

Mai 2008
LMMJVSD
   1234
567891011
12131415161718
19202122232425
262728293031 

VS Express FR Gratuit !

VS Express en français et 100% gratuit !

Boutique

Boutique de goodies CodeS-SourceS