Historique des modifications - Message

Message #1768

Sujet: [reseau] Gestion multi-thread


Type Date Auteur Contenu
Création du message 04-03-2007 03:01:40 maitrelame12545
Bonjour !
J'aimerais vous introduire a la creation d'un serveur multi-thread avec winsock2.

Je vais essayer d'etre le plus clair possible !

Tout d'abord cree un projet sous votre compilateur.
Vous devez linker la lib : ibws2_32.apour que cela marche.

voici le main :

 
#include "serveur.h" 
#include <iostream> 
 
using namespace std;

int main()
{
//on cree le serveur et nous gerons les erreurs
	serveur *MyServer = new serveur(1000);
	if(MyServer->init()!=0){
		cerr << "ne peut initialiser le serveur"<< endl;
		return 1;
	}
 //On lance le serveur afin d'attendre les connexions et aussi gerer les fonctions des clients
	if(MyServer->start()!=0){
		cerr << "ne peut demarrer le serveur"<< endl;
		return 1;
	}
    
	return 0;
}

serveur.cpp
#include <winsock2.h>//On link winsock
#include "serveur.h"

#define _MAX_HOST_LENGTH_ 100
//taille maximum de l'adresse du serveur


serveur::serveur(int p){
	port	= p;
	running	= false;
}

int serveur::init(){
	struct in_addr  MyAddress;//Votre ip
	struct hostent  *host;
	char HostName[_MAX_HOST_LENGTH_];//Le nom sous lequel vous serez identifier
	WSADATA	      wsaData;
//WSADATA correspond a tous les paramettre du serveur


//Si l'initialisation des paramettre echoue on quitte
	if(WSAStartup(MAKEWORD(2,2), &wsaData ) != 0 )
        {
		cerr <<"WSAStartup a echoue "<< endl;
		return 1;
	}
//Si la fonction qui permet de connaitre votre ip echoue on quitte
	if( gethostname( HostName, _MAX_HOST_LENGTH_ ) == SOCKET_ERROR ){
		cerr<< "gethostname() a rencontre l'erreur "<< WSAGetLastError()  << endl;
		return 1;
	}
//Si le nom de l'hote ne peut pas etre trouver on quitte
	if( (host = gethostbyname( HostName ) ) == NULL){
		cerr <<"gethostbyname() a rencontre l'erreur "<< WSAGetLastError()<< endl;
		return 1;
	}

	memcpy( &MyAddress.s_addr, host->h_addr_list[0], sizeof( MyAddress.s_addr ) );
//On met en memoire l'hote, et l'ip du serveur

	ServerAddr.sin_family = AF_INET;//L'adresse du serveur
	ServerAddr.sin_port = htons( port );//Le port du serveur
	ServerAddr.sin_addr.s_addr = inet_addr( inet_ntoa( MyAddress ) );
//Les paramettre hostName et IP

	cout <<"Serveur correctement initialise" << endl;
	return 0;
}

//Fonction de lancement
int serveur::start (){
	SOCKADDR_IN            ClientAddr;// Adresse du client
	int                              ClientAddrLen; // Taille de don adresse
	HANDLE                      hProcessThread; //Processus du client
	SOCKET                      NewConnection; // Nouvelle connexion
	struct thread_param         p;//Strucure dans serveur.h

     initMysql();//J'utilise l'api mysql donc j'utilise ma fonction d'initialisation.
//Vous devez l'enlevez dans vos programme car c'est une fonction personaliser

	if( ( ListeningSocket = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ){
		cerr << "ne peut creer la socket. Erreur n° " << WSAGetLastError()<< endl;
		WSACleanup();
		return 1;
	}//Si le socket du client est invalid ou contient un mauvais paramettre on vide les paramettre et on tue la connexion

	if( bind( ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof( ServerAddr ) ) == SOCKET_ERROR ){
		cerr << "bind a echoue avec l'erreur " << WSAGetLastError() << endl;
		cerr << "Le port est peut-etre deja utilise par un autre processus " << endl;
		closesocket( ListeningSocket );
		WSACleanup();
		return 1;
	}// Si les infos de connexion ne sont pas correcte on netoie et on tue la connexion

	if( listen( ListeningSocket, 5 ) == SOCKET_ERROR ){
		cerr << "listen a echoue avec l'erreur " << WSAGetLastError() << endl;
		closesocket( ListeningSocket );
		WSACleanup();
		return 1;
	}// Si l'acquistion des paramettre ou une erreur sur le flux de transmission se produit on tue la connexion

	cout << "serveur demarre : a l'ecoute du port " << port << endl;
	running = true;
//On informe sur le port ecouter
	ClientAddrLen = sizeof( ClientAddr );
//On donne la taille des adresses

	while(running){
		if((NewConnection = accept( ListeningSocket, (SOCKADDR *) &ClientAddr, &ClientAddrLen)) == INVALID_SOCKET){
			cerr  << "accept a echoue avec l'erreur " << WSAGetLastError() << endl;;
			closesocket( ListeningSocket );
			WSACleanup();
			return 1;
		}//Tant que le serveur est en route on accepte les connexion sauf si une erreur se produit

		p.ser = this;//Paramettre du serveur
		p.soc = NewConnection;//Creation du socket

		cout << "client connecte ::  IP : " <<inet_ntoa( ClientAddr.sin_addr )<< " ,port = " <<ntohs( ClientAddr.sin_port ) << endl;
// Informe de la connexion d'un client

		hProcessThread = CreateThread(NULL, 0,&serveur::ThreadLauncher, &p,0,NULL);
		if ( hProcessThread == NULL ){
			cerr << "CreateThread a echoue avec l'erreur " <<GetLastError()<< endl;
		}//on creer le processus du client
	}

	return 0;
}

int serveur::pause (){
	running = false;
	cout << "Serveur en pause" << endl;
	closesocket( ListeningSocket );
	return 0;
}

/* ======================================================================== */
/* ========================== thread proc ================================= */
/* ======================================================================== */

//Code relatif au serveur
DWORD serveur::ClientThread(SOCKET soc){
	cout << "thread client demarre" << endl;
    send(soc, "salut", 6, 0);//j'envoie un message d'acceuil
    recv(soc, buffer, sizeof(buffer), 0);//Je reois un message venant du client
//buffer est dans la classe serveur
    cout << buffer << endl;//J'affiche le buffer
   	return 0;
}

serveur.h
#ifndef __serveur_h__ 
#define __serveur_h__ 

#include <winsock2.h>
#include <iostream>

using namespace std;

class serveur;

/////////////Classe paramettre des processus thread//////////////////////
struct thread_param{
       serveur* ser;
       SOCKET soc;
};


class serveur{
	private: 
        /////////////////////////////Donne sur le serveur//////////////////////////
		int           port;
		SOCKET	      ListeningSocket;
		bool          running;  
		SOCKADDR_IN   ServerAddr;   
		DWORD         ClientThread(SOCKET);  
	public:                                                  
		serveur(int);
		int                 init();
		int                 start ();  
		int                 pause ();
		static DWORD WINAPI ThreadLauncher(void *p){
			struct thread_param *Obj = reinterpret_cast<struct thread_param*>(p);               
			serveur *s = Obj->ser;                          
			return s->ClientThread(Obj->soc);       
		}
		char buffer[255];

}; 



#endif

Voila j'espere que cela vous auras plus !

Prochain tuto : Un client !
suivant tuto : API MYSQL
Dernier tuto : OpenAL

Retour

Options Liens officiels Caractéristiques Statistiques Communauté
Préférences cookies
Corrections
irrlicht
irrklang
irredit
irrxml
Propulsé par Django
xhtml 1.0
css 2.1
884 membres
1440 sujets
11337 messages
Dernier membre inscrit: Saidov17
152 invités en ligne
membre en ligne: -
RSS Feed