Accueil > > > [WIN32] CLASSE DE CONTROLE DE WINSOCK MODE MULTITHREAD
[WIN32] CLASSE DE CONTROLE DE WINSOCK MODE MULTITHREAD
Information sur la source
Description
Salut ! Bon ben voilà... tout est dans le titre : il s'agit d'une classe (HelkSock) qui permet de controler facilement des winsocks, et ceci de manière multi-thread... L'utilisation est simple, le code un peu plus fouillis... dans le zip, il y a un autre exemple (que ci-dessous) de l'utilisation de la classe HelkSock, qui utilise QT (donc prévoyez les DLL pour faire fonctionner le .exe)
Source
- //Principe de fonctionnement
- HelkSock HKS(true); //true pour TCP, false pour UDP
-
- //pour se connecter à un hote distant, à l'adresse IP 125.124.123.122 sur le port 1234 :
- HKS.Connecter("125.124.123.122", 1234);
-
- //pour se mettre en écoute (listen), cad en attente avec le port 1234 ouvert :
- HKS.Ecouter(1234);
-
- //pour se déconnecter :
- HKS.Fermer();
-
- //rien de plus simple, donc... mais tout ça c'est bien beau, cependant c'est inutile...
- //en effet le but est évidemment d'envoyer et de recevoir des données...
- //pour envoyer c'est encore très simple :
- char pcBuffer [200] = "Ceci est mon message";
- HKS.Envoyer(pcBuffer, strlen(pcBuffer));
-
- //pour l'instant, pas de problème
- //mais qu'en est-il de la réception ?
-
- /* C'est là que l'aspect multi-thread de ma classe intervient...
- En effet on définit, si possible avant utilisation de l'objet, des fonctions
- qui serviront de récepteurs pour les différents messages que le HelkSock va
- pouvoir vouloir envoyer... Je me suis pour cela basé sur le principe de fonctionnement des Winsock Control en VB et du système de slots en QT
- Voilà comment ça marche : */
- HKS.LierSlot1(SLOT_REQUETE, ConnexionEffectuee);
- //où ConnexionEffectuee est une fonction de la forme :
- //HELKSLOT Slot (); //HELKSLOT = int
- //ou encore
- HKS.LierSlot2(SLOT_REQUETE, RequeteDeConnexion);
- //où on a RequeteDeConnexion de la forme
- //HELKSLOT Slot(const char * pcBuffer, const ulong uLongVal);
- //et aussi, le dernier type de Slot :
- HKS.LierSlot3(SLOT_PROGRESSION, ProgressionEnvoi);
- //avec progressionEnvoi qui prend pour arguments (ulong uOctetsEnvoyes, ulong uOctetsRestants)
-
- //ceci dit, on peut simplifier les choses en utilisant LierTousSlots,
- //qui ne lie que les slots non NULLs, et qui permet en une ligne d'initialiser correctement la classe
-
- /* Maintenant observons le comportement :
- On a "lié" la fonction
- HELKSLOT RecevoirDonnees(const char * pcDonneesRecues, const ulong uLongueurDonnees);
- à la classe pour indiquer l'événement Réception de données (cad SLOT_RECEPTION)
- Une fois que l'on sera connecté, on recevra immédiatement, et sans rien faire, les données dans cette fonction ! voilà tout l'intérêt de la classe...
- De meme, 4 (oui c'est peu) messages d'erreur peuvent parvenir à une fonction Erreur, et on peut connaitre l'état d'avancement d'un envoi grace à un slot relié à l'événement SLOT_PROGRESSION.
-
- Voici donc un exemple de code pour clarifier les choses (enfin j'espère) : */
-
- #include <iostream>
- #include <string>
- #include <stdlib.h>
- #include <conio.h>
- #include <ctime>
- using namespace std;
-
- #include "helksock1.h"
-
- HELKSLOT RequeteDeConnexion(const char * pcAdresseIP, const ulong uPortDistant);
- HELKSLOT RecevoirDonnees(const char * pcDonneesRecues, const ulong uLongueurDonnees);
- HELKSLOT ConnexionEffectuee();
- HELKSLOT FermetureHSocket();
- HELKSLOT ErreurHSocket(const char * pcErreurDescr, const ulong uErrNum);
- HELKSLOT EnvoiEnCours(ulong uEnvoyes, ulong uRestants);
- HELKSLOT FinEnvoi();
-
-
- HelkSock hks;
-
- int main()
- {
- srand(time(0));
- cout << "Lancement du HelkSock..." << endl;
- hks.LierTousSlots(RequeteDeConnexion,
- ConnexionEffectuee,
- RecevoirDonnees,
- EnvoiEnCours,
- FinEnvoi,
- FermetureHSocket,
- ErreurHSocket
- );
- ///*
- //tout d'abord, on essaie de fonctionner en mode serveur, cad qu'on écoute sur le port 42201
- //grace à un autre programme, on peut se connecter sur ce port et envoyer un message, qui sera reçu
- hks.Ecouter(42200);
-
- cout << "Si vous voulez arreter, enfoncez la touche ENTREE" << endl
- << "Sinon vous pouvez envoyer des mots ou attendre d'en recevoir" << endl;
- string sEnvoi;
-
- char pcBuffer [500] = {0};
- cout << "Veuillez enfoncer une touche quelconque pour continuer ou ENTREE pour quitter..." << endl;
- while (getch() != '\r')
- {
- cout << "Veuillez entrer une phrase a envoyer" << endl;
- cin >> sEnvoi;
- //on envoie le message tapé
- if (!hks.Envoyer(sEnvoi.c_str(), sEnvoi.length()))
- cout << "ERREUR lors de l'envoi : un autre envoi semble etre en cours" << endl;
- Sleep(100);
- cout << "Veuillez enfoncer une touche quelconque pour continuer ou ENTREE pour quitter..." << endl;
- }
-
- cout << "On attend un peu..." << endl;
- Sleep(2500); //il me faut le temps de mettre l'autre prog en écoute
- //maintenant on veut se connecter à un hote "distant" (127.0.0.1 = localhost)
- hks.Fermer();
- cout << "Tentative de connexion sur soi-meme au port 42201" << endl;
- if (hks.Connecter("127.0.0.1", 42201))
- {
- char pcBuffer [500] = {0};
- cout << "Veuillez enfoncer une touche quelconque pour continuer ou ENTREE pour quitter..." << endl;
- while (getch() != '\r')
- {
- cout << "Veuillez entrer une phrase a envoyer" << endl;
- cin >> sEnvoi;
- //on envoie le message tapé
- if (!hks.Envoyer(sEnvoi.c_str(), sEnvoi.length()))
- cout << "ERREUR lors de l'envoi : un autre envoi semble etre en cours" << endl;
- Sleep(100);
- cout << "Veuillez enfoncer une touche quelconque pour continuer ou ENTREE pour quitter..." << endl;
- }
- }
- //*/
-
- return 0;
- }
-
- //en cas de requete de connexion, l'utilisateur peut être averti
- HELKSLOT RequeteDeConnexion(const char * pcAdresseIP, const ulong uPortDistant)
- {
- cout << "Requete de connexion de la part de " << pcAdresseIP << " sur le port " << uPortDistant << endl;
- return true; //si on retourne false, alors il y a déconnexion et on attend encore, sinon on accepte et...
- }
-
- //...une fois la connexion effectuée, on prévient l'utilsateur
- HELKSLOT ConnexionEffectuee()
- {
- cout << "La connexion vient de se faire" << endl;
- if (!BLOQUER_ECOUTE)
- hks.LancerReception();
- return true;
- }
-
- //ici on recoit en permanence ce que le pc distant veut nous envoyer
- HELKSLOT RecevoirDonnees(const char * pcDonneesRecues, const ulong uLongueurDonnees)
- {
- cout << "Recu : " << pcDonneesRecues << endl;
- return true;
- }
-
- //cette fonction est appelée dès que la connexion est coupée
- HELKSLOT FermetureHSocket()
- {
- cout << "La connexion vient d'etre coupee" << endl;
- return true;
- }
-
- //gestion des erreurs
- HELKSLOT ErreurHSocket(const char * pcErreurDescr, const ulong uErrNum)
- {
- cout << "\7Erreur n " << uErrNum << " :\r\n" << pcErreurDescr << endl;
- return true;
- }
-
- //on peut afficher la progression d'un envoi plus gros que la taille par défaut du buffer d'envoi (100 octets ici)
- HELKSLOT EnvoiEnCours(ulong uEnvoyes, ulong uRestants)
- {
- cout << "Progression : " << uEnvoyes << " octets envoyes + " << uRestants << " octets restants" << endl;
- return true;
- }
-
- //l'envoi est fini (utile pour des paquets assez gros)
- HELKSLOT FinEnvoi()
- {
- cout << "L'envoi est terminé" << endl;
- return true;
- }
//Principe de fonctionnement
HelkSock HKS(true); //true pour TCP, false pour UDP
//pour se connecter à un hote distant, à l'adresse IP 125.124.123.122 sur le port 1234 :
HKS.Connecter("125.124.123.122", 1234);
//pour se mettre en écoute (listen), cad en attente avec le port 1234 ouvert :
HKS.Ecouter(1234);
//pour se déconnecter :
HKS.Fermer();
//rien de plus simple, donc... mais tout ça c'est bien beau, cependant c'est inutile...
//en effet le but est évidemment d'envoyer et de recevoir des données...
//pour envoyer c'est encore très simple :
char pcBuffer [200] = "Ceci est mon message";
HKS.Envoyer(pcBuffer, strlen(pcBuffer));
//pour l'instant, pas de problème
//mais qu'en est-il de la réception ?
/* C'est là que l'aspect multi-thread de ma classe intervient...
En effet on définit, si possible avant utilisation de l'objet, des fonctions
qui serviront de récepteurs pour les différents messages que le HelkSock va
pouvoir vouloir envoyer... Je me suis pour cela basé sur le principe de fonctionnement des Winsock Control en VB et du système de slots en QT
Voilà comment ça marche : */
HKS.LierSlot1(SLOT_REQUETE, ConnexionEffectuee);
//où ConnexionEffectuee est une fonction de la forme :
//HELKSLOT Slot (); //HELKSLOT = int
//ou encore
HKS.LierSlot2(SLOT_REQUETE, RequeteDeConnexion);
//où on a RequeteDeConnexion de la forme
//HELKSLOT Slot(const char * pcBuffer, const ulong uLongVal);
//et aussi, le dernier type de Slot :
HKS.LierSlot3(SLOT_PROGRESSION, ProgressionEnvoi);
//avec progressionEnvoi qui prend pour arguments (ulong uOctetsEnvoyes, ulong uOctetsRestants)
//ceci dit, on peut simplifier les choses en utilisant LierTousSlots,
//qui ne lie que les slots non NULLs, et qui permet en une ligne d'initialiser correctement la classe
/* Maintenant observons le comportement :
On a "lié" la fonction
HELKSLOT RecevoirDonnees(const char * pcDonneesRecues, const ulong uLongueurDonnees);
à la classe pour indiquer l'événement Réception de données (cad SLOT_RECEPTION)
Une fois que l'on sera connecté, on recevra immédiatement, et sans rien faire, les données dans cette fonction ! voilà tout l'intérêt de la classe...
De meme, 4 (oui c'est peu) messages d'erreur peuvent parvenir à une fonction Erreur, et on peut connaitre l'état d'avancement d'un envoi grace à un slot relié à l'événement SLOT_PROGRESSION.
Voici donc un exemple de code pour clarifier les choses (enfin j'espère) : */
#include <iostream>
#include <string>
#include <stdlib.h>
#include <conio.h>
#include <ctime>
using namespace std;
#include "helksock1.h"
HELKSLOT RequeteDeConnexion(const char * pcAdresseIP, const ulong uPortDistant);
HELKSLOT RecevoirDonnees(const char * pcDonneesRecues, const ulong uLongueurDonnees);
HELKSLOT ConnexionEffectuee();
HELKSLOT FermetureHSocket();
HELKSLOT ErreurHSocket(const char * pcErreurDescr, const ulong uErrNum);
HELKSLOT EnvoiEnCours(ulong uEnvoyes, ulong uRestants);
HELKSLOT FinEnvoi();
HelkSock hks;
int main()
{
srand(time(0));
cout << "Lancement du HelkSock..." << endl;
hks.LierTousSlots(RequeteDeConnexion,
ConnexionEffectuee,
RecevoirDonnees,
EnvoiEnCours,
FinEnvoi,
FermetureHSocket,
ErreurHSocket
);
///*
//tout d'abord, on essaie de fonctionner en mode serveur, cad qu'on écoute sur le port 42201
//grace à un autre programme, on peut se connecter sur ce port et envoyer un message, qui sera reçu
hks.Ecouter(42200);
cout << "Si vous voulez arreter, enfoncez la touche ENTREE" << endl
<< "Sinon vous pouvez envoyer des mots ou attendre d'en recevoir" << endl;
string sEnvoi;
char pcBuffer [500] = {0};
cout << "Veuillez enfoncer une touche quelconque pour continuer ou ENTREE pour quitter..." << endl;
while (getch() != '\r')
{
cout << "Veuillez entrer une phrase a envoyer" << endl;
cin >> sEnvoi;
//on envoie le message tapé
if (!hks.Envoyer(sEnvoi.c_str(), sEnvoi.length()))
cout << "ERREUR lors de l'envoi : un autre envoi semble etre en cours" << endl;
Sleep(100);
cout << "Veuillez enfoncer une touche quelconque pour continuer ou ENTREE pour quitter..." << endl;
}
cout << "On attend un peu..." << endl;
Sleep(2500); //il me faut le temps de mettre l'autre prog en écoute
//maintenant on veut se connecter à un hote "distant" (127.0.0.1 = localhost)
hks.Fermer();
cout << "Tentative de connexion sur soi-meme au port 42201" << endl;
if (hks.Connecter("127.0.0.1", 42201))
{
char pcBuffer [500] = {0};
cout << "Veuillez enfoncer une touche quelconque pour continuer ou ENTREE pour quitter..." << endl;
while (getch() != '\r')
{
cout << "Veuillez entrer une phrase a envoyer" << endl;
cin >> sEnvoi;
//on envoie le message tapé
if (!hks.Envoyer(sEnvoi.c_str(), sEnvoi.length()))
cout << "ERREUR lors de l'envoi : un autre envoi semble etre en cours" << endl;
Sleep(100);
cout << "Veuillez enfoncer une touche quelconque pour continuer ou ENTREE pour quitter..." << endl;
}
}
//*/
return 0;
}
//en cas de requete de connexion, l'utilisateur peut être averti
HELKSLOT RequeteDeConnexion(const char * pcAdresseIP, const ulong uPortDistant)
{
cout << "Requete de connexion de la part de " << pcAdresseIP << " sur le port " << uPortDistant << endl;
return true; //si on retourne false, alors il y a déconnexion et on attend encore, sinon on accepte et...
}
//...une fois la connexion effectuée, on prévient l'utilsateur
HELKSLOT ConnexionEffectuee()
{
cout << "La connexion vient de se faire" << endl;
if (!BLOQUER_ECOUTE)
hks.LancerReception();
return true;
}
//ici on recoit en permanence ce que le pc distant veut nous envoyer
HELKSLOT RecevoirDonnees(const char * pcDonneesRecues, const ulong uLongueurDonnees)
{
cout << "Recu : " << pcDonneesRecues << endl;
return true;
}
//cette fonction est appelée dès que la connexion est coupée
HELKSLOT FermetureHSocket()
{
cout << "La connexion vient d'etre coupee" << endl;
return true;
}
//gestion des erreurs
HELKSLOT ErreurHSocket(const char * pcErreurDescr, const ulong uErrNum)
{
cout << "\7Erreur n " << uErrNum << " :\r\n" << pcErreurDescr << endl;
return true;
}
//on peut afficher la progression d'un envoi plus gros que la taille par défaut du buffer d'envoi (100 octets ici)
HELKSLOT EnvoiEnCours(ulong uEnvoyes, ulong uRestants)
{
cout << "Progression : " << uEnvoyes << " octets envoyes + " << uRestants << " octets restants" << endl;
return true;
}
//l'envoi est fini (utile pour des paquets assez gros)
HELKSLOT FinEnvoi()
{
cout << "L'envoi est terminé" << endl;
return true;
}
Conclusion
Il semble rester quelques bugs, notamment celui ci: - il est possible (parfois seulement) d'envoyer des messages apres deconnexion, ce qui évidemment genere un message d'erreur Ceci dit, la classe mériterait d'être encore un peu améliorée (cf interactions threads et objet HelkSock...), et la gestion des erreurs devrait être un peu (beaucoup) améliorée
je suis ouvert à toute suggestion, remarque ou demande éventuelle...
a++ et bonne prog à tous Helkanen
ps: comment peut-on connaitre le port local sur lequel le socket s'est branché (écoute ou connexion) ?
Sources du même auteur
Sources de la même categorie
Commentaires et avis
|
Derniers Blogs
IMAGINE CUP 2012, MAKE A SIGN EN FINALEIMAGINE CUP 2012, MAKE A SIGN EN FINALE par junarnoalg
Voilà qui est fait, la nouvelle est officielle ! L'équipe belge "Make a Sign" va au pays des kangourous défendre son projet dans la catégorie Software Design. http://www.imaginecup.com/CompetitionsContent/Competition/WorldwideFinalists.aspx V...
Cliquez pour lire la suite de l'article par junarnoalg KINECT 1.5 IS OUT !KINECT 1.5 IS OUT ! par Vko
La version 1.5 du Kinect For Microsoft vient tout juste de sortir ! Plein de nouveautés: Tracking de squelette en Near Mode Détection en position assise Détection faciale avec un SDK dédié Documentation et des guideline (enfin) Un out...
Cliquez pour lire la suite de l'article par Vko LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) par richardc
Mise à jour des Web API du 14 Mai
Réservez dès maintenant votre journée du 20 juin pour le Windows Azure Dev Camp 2012 à Paris
Mise à jour de Team Foundation Service
MechCommander 2 sur Windows 8
Entity Framework 5 Release Candidate e...
Cliquez pour lire la suite de l'article par richardc REACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITERREACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITER par Groc
Une mauvaise utilisation de rx lors de l'écriture d'une couche d'accès à des services peut conduire à des cas embarassants avec des erreurs mal gérées, des appels qui ne partent lorsqu'ils le devraient, et même des résultats incorrects . le tout nuis...
Cliquez pour lire la suite de l'article par Groc SHAREPOINT BLOG SITE, PROBLèME D'ARCHIVESSHAREPOINT BLOG SITE, PROBLèME D'ARCHIVES par junarnoalg
Dernièrement, nous avons migré le site
myTIC
vers un nouveau serveur SharePoint 2010. Dans les contenus que nous vouloins récupérer, nous avions un certain nombre de blogs.
Nous avons utilisé les commandes Power...
Cliquez pour lire la suite de l'article par junarnoalg
Forum
RE : SAC A DOS RE : SAC A DOS par hadjkaddour
Cliquez pour lire la suite par hadjkaddour
Logiciels
sDEVIS-FACTURES vlPRO (8.1.0.3)SDEVIS-FACTURES VLPRO (8.1.0.3)sDEVIS-FACTURES vlPRO a été mis au point pour les particuliers, créateurs, entrepreneurs, artisa... Cliquez pour télécharger sDEVIS-FACTURES vlPRO 974 Application Server (12.2.4.6)974 APPLICATION SERVER (12.2.4.6)Développez de puissantes applications dans un environnement de 'cloud computing', clusterisé, séc... Cliquez pour télécharger 974 Application Server vPicture (1.4.2.1)VPICTURE (1.4.2.1)Avec vPicture, hébergez vos images facilement et rapidement.
vPicture est un utilitaire simple, ... Cliquez pour télécharger vPicture Easy-Planning (2.2.1.6)EASY-PLANNING (2.2.1.6)Easy-Planning permet de créer des plannings sous la représentation de diagrammes et est adapté au... Cliquez pour télécharger Easy-Planning COM-BACKUP (2.0)COM-BACKUP (2.0)
COM-BACKUP est un logiciel de sauvegarde qui permet de planifier les sauvegardes de vos dossiers ...
Cliquez pour télécharger COM-BACKUP
|