Historique des modifications - Message

Message #1768

Sujet: [reseau] Gestion multi-thread


TypeDateAuteurContenu
Création du message04-03-2007 03:01:40maitrelame12545
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

OptionsLiens officielsCaractéristiquesStatistiquesCommunauté
Préférences cookies
Corrections
irrlicht
irrklang
irredit
irrxml
Propulsé par Django
xhtml 1.0
css 2.1
884 membres
1441 sujets
11339 messages
Dernier membre inscrit: Saidov17
108 invités en ligne
membre en ligne: -
RSS Feed