04-03-2007 03:01:40
- maitrelame12545
- Membres

- Date d'inscription:
- Messages: 51
- IP: 76.80.53.159
- Courriel
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];
};
#endifVoila j'espere que cela vous auras plus !
Prochain tuto : Un client !
suivant tuto : API MYSQL
Dernier tuto : OpenAL
Codeur elewendyl
Hors ligne
04-03-2007 10:49:21
- khayyam
- Membres
- Date d'inscription:
- Messages: 25
- IP: 90.13.179.126
- Courriel Site web
Salut,
Si déjà tu veux écrire un tuto sur les serveurs multithreads avec winsock 2 en repompant un code, essaie de mettre les infos qui vont avec pour que le tuto puisse être compris.
http://khayyam.developpez.com/articles/cpp/multithreads/
Hors ligne
04-03-2007 16:45:35
- maitrelame12545
- Membres

- Date d'inscription:
- Messages: 51
- IP: 76.80.53.159
- Courriel
Ton code est si bien taper que je voix pas comment faire mieu...
A part virer les les messages d'erreur difficille de faire mieu...
Je voulais te demander si tu voulais pas partciper avec moi pour faire le tuto de irrlicht.
Je viens de finir d'ecrire la partie sur les translations.
A+
Codeur elewendyl
Hors ligne
10-10-2009 12:41:47
- TUpac
- Membres

- Date d'inscription:
- Messages: 387
- IP: 88.168.3.38
- Courriel
Bon tuto, même si c'est un peu léger pour quelqu'un qui n'a jamais touché au reseau.
En tout cas ce genre de serveur est bien utile mais il ne faut pas l'utiliser dans un projet de serveur de jeu.
En effet, pour des test ça marche bien mais c'est extrèmement gourmand en CPU.
Il vaut mieux utiliser deux ou trois threads contenant des sockets multiplexés par select().
"Si vous ne partagez pas votre stabilité avec les pauvres, les pauvres partageront leur instabilité avec vous."
Hors ligne



