begin process at 2012 05 27 19:33:09
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Réseaux & Internet

 > [WIN32] CLASSE DE CONTROLE DE WINSOCK MODE MULTITHREAD

[WIN32] CLASSE DE CONTROLE DE WINSOCK MODE MULTITHREAD


 Information sur la source

Note :
9,6 / 10 - par 5 personnes
9,60 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Réseaux & Internet Niveau :Débutant Date de création :14/04/2004 Vu / téléchargé :5 419 / 564

Auteur : Helkanen

Ecrire un message privé
Site perso
Commentaire sur cette source (6)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
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) ?

 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 Source avec une capture [WIN : QT -> VC++] ADAPTATEUR DE PROJET QT POUR VC++
Source avec Zip Source avec une capture API - QUELQUES EXEMPLES D'UTILISATIONS DES API WIN32

 Sources de la même categorie

Source avec Zip Source avec une capture MINI SERVEUR HTTP [WINDOWS] par ganjarasta
Source avec Zip Source avec une capture CLIENT DE TEST MODBUS TCP par brunovan
Source avec Zip Source avec une capture SCANIP [ARP / ICMP] par ganjarasta
Source avec Zip Source avec une capture TRACEROUTE [WINPCAP] par ganjarasta
Source avec Zip SERVEUR MULTITHREAD [LINUX/WIN] par nipepsinicolas

Commentaires et avis

Commentaire de Kirua le 15/04/2004 03:51:48

Si j'en crois la description que j'ai lu avec grand intérêt, tu as atteint le modèle idéal de classe de socket :-) elle fait tout ce qu'on en attend. Reste à la rendre portable ^^ pour ça faudrait savoir comment fonctionnent les sockets en natif sur les autres OS et puis à coup de commandes préprocesseurs élargir le code, dy style comme ça:

type fonction(paramètres)
{
#ifdef WIN32
  ... code winsocks
#endif

#ifdef LINUX
  ... sockets linux
#endif

...
}


parce qu'une classe non portable, c'est triste ^^

Bonne continuation, en tt cas ta classe est très allechante, et je trouve le système de liaison à des fonctions très intéressant.

Commentaire de Helkanen le 16/04/2004 09:51:36

merci bcp pour ce commentaire...
en effet le mieux serait de la rendre portable...
mais contrairement à ce qu'on dit sur Linux (stabe et tout) j'ai eu plein de problemes en l'installant sur mon pc... (c'est bien dommage)
donc je ne maîtrise pas vraiment cet OS et encore moins la programmation LINUX, mais cela ne saurait tarder... ;)
elle mérite encore d'être améliorée, notamment pour implémenter les fonctions gethostname... et pour récupérer les IP locales et le port local ouvert (si possible)

a++ et bonne prog à toi aussi (3h51 c pas une heure ! :p)
helkanen

Commentaire de marsu73 le 30/04/2004 00:09:27

Salut ; très pratique tes sources, merci ;
par contre j'ai un petit soucis.
Je suis sous VC++ .NET et je n'arrive qu'à avoir 2 clients maxi qui se connectent..ensuite je suis obligé de relancé l'application, sinon plus rien ne se passe et sa commence à ramer.
Je n'ai pas inséré dans mon code la ligne  srand(time(0));   et je ne traite pas encore les envois de données.
As-tu déja rencontré ce probleme ?

Merci d'avance !

Commentaire de Helkanen le 30/04/2004 19:06:08

ben a vrai dire j'ai pas encore trop utilise ma classe ( :S )
en fait j'ai meme pas essayé d'utiliser plusieurs HelkSock en meme temps...
en tout cas, ca me fait plaisir de savoir que ma classe peut etre utile à qqn (pour une fois !)

faudra que je me remette a travailler sur la source (elle mériterait encore qqes ameliorations) mais la g pas vraiment le temps (pfff bac blanc)
si jamais tu trouves la solution, préviens moi en je ferai le nécessaire

a++ et bonne prog
Helkanen

ps : comme je l'ai déjà dit : minuit c pas une heure (hehe, pour moi c souvent pareil :p )

Commentaire de Helkanen le 30/04/2004 19:07:45

au fait, je sais pas qui m'a mis 9/10 mais je lui en suis bien reconnaissant ;p

Commentaire de AmK le 26/10/2004 16:20:10

Non y'en a un qui t'a mis 10 et un autre 8 !

 Ajouter un commentaire




Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
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,374 sec (3)

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