begin process at 2012 02 10 03:16:07
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Réseaux & Internet

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

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


 Information sur la source

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

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
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é :6 797 / 676

Auteur : cosmobob

Ecrire un message privé
Ce membre participe au partage de revenus publicitaires
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.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Sources du même auteur

Source avec Zip POINTEUR INTELLIGENT : CLASSE TEMPLATE POUR S'AFFRANCHIR TOT...
Source avec Zip Source avec une capture SNIFFER MSN MESSENGER GRACE AU HOOK DES FONCTIONS WINSOCK
Source avec Zip Source avec une capture PORTS ACTIFS : LISTE LES CONNECTIONS TCP ET UDP EN COURS DE ...
Source avec Zip Source avec une capture BIJECTION EXPLICITE ENTRE N ET Q+
Source avec Zip BOT IRC TOUT SIMPLE, FAIT A L'AIDE DE LA CLASSE PROSOCK

 Sources de la même categorie

Source avec Zip SERVEUR MULTITHREAD [LINUX/WIN] par nipepsinicolas
Source avec Zip Source avec une capture SECURE REMOTE SHELL [WIN32] par ganjarasta
Source avec Zip Source avec une capture SUIVI DE PRODUCTION ONDULEUR PHOTOVOLTAÏQUE SOLARMAX par brunovan
Source avec Zip MINICHAT MULTI-CLIENT par wisar
SOCKET CPP par baptchr55

Commentaires et avis

Commentaire de cosmobob le 18/02/2004 16:59:24

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

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 ...

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

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 ...

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...

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...

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

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

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

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...

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

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);

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?

Commentaire de SnOOpss le 14/09/2006 18:49:02

c'est quoi ton message d'erreur ?

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,577 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales