Comment Gerer des sockets non bloquant sous OpenGl
cs_kawito
Messages postés24Date d'inscriptiondimanche 20 juillet 2003StatutMembreDernière intervention13 décembre 2005
-
20 juil. 2003 à 17:34
kwisatz_haderach
Messages postés5Date d'inscriptionmardi 23 décembre 2003StatutMembreDernière intervention 3 janvier 2004
-
3 janv. 2004 à 14:16
Bonjour,
je devellope un jeu (2d + scene 3d) en Opengl et C++, je desire utiliser seulement opengl et c++ (console app), pour des raisons de portabilitée,donc pas de MFC !
et biensur j'aimerais que ce jeu ce joue en reseau :
j'ai donc fais un client serveur tcp (winsock version 1.1)
mais les fonction accept et recv sont bloquante ,
mon serveur passe en ecoute ,puis je fais un accept sur le socket client (1er client)
la fonction accept et bloquante !
j'ai donc cherché comment faire pour eviter ce probleme, et la je bloque un peu ?
j'ai bien vu des truc comme SWAAsyncSelect(socket,hWnd,wMsg,Event);
comment reccuperer les messages de windows wMsg sous opengl et l'identificateur de la fenetre ?
pour que je puisse utiliser les fonctions du type WSA
je voudrais que le serveur detecte une nouvelle connexion cliente :
une fois mon serveur en ecoute je voudrais qu'il scrute les evenements network, pour faire selon un accept un send ou un recv.
le serveur possede une liste dynamique de socket client
si evenement network FD_ACCEPT
creer cellule socket cliente
faire un accet sur ce socket
connexion acceptée ?
scruter les evenements j'usqu'au prochain accept et on recommence, creation de la cellule socket cliente et accept...
ainsi je pense que meme si la fonction accept et bloquante
vu que je detecte une demande de connexion avant de lancer la fonction accept, cela devrais fonctionner ?
ou peut etre faut il utiliser les threads ,mais la j'ai pas tous compris !
comment utiliser un thread sous opengl sans MFC
AUTRE SOUCIS :
j'utilise winsock 1.1 car losrque j'inclus winsock2.h
avec la lib ws2_32.lib
j'ai des erreurs sur fd_set redefined etc......
impossible d'utiliser winsock version 2 !
ya t'il un probleme dans windows.h, il me semble que winsock.h est systematiquement implementé ,ou quil manque des directives dans winsock2.h ?
AUTRE QUESTION:
quel est l'architecture d'un programme complex en opengl sans MFC,ou placer les traitements du programme ?
comme la getion des sockets reseau
cs_aardman
Messages postés1905Date d'inscriptionmercredi 22 janvier 2003StatutMembreDernière intervention17 septembre 20123 20 juil. 2003 à 19:34
Salut,
1) WSA=> windows socket api => winsock 2
Donc je pense pas que tu puisse utiliser les fonctions WSA en socket 1.1.
2) Ensuite, la fonction WSAAsyncSelect transcrit les evenement reseau en messages windows, donc il te faut une fenetre (meme invisible) pour recevoir et traiter les messages.
Pour detecter et accepter une nouvelle connection, tu traite FD_ACCEPT. Dans ce message, ou plutot cette notification de message, tu met tout tes trucs: tu crée tes cellules, tu accepte la connection... Si accept retourne autre chose que INVALID_SOCKET, c'est que la connection a reussi.
3) Enfin, pour les erreurs de definition,
- soit tu inclus winsock2.h avant windows.h (ca c si tu as juste des probs de redefinition avec winsock2.h)
- soit tu met tout en haut, avant tout les header:
#define _WIN32_WINNT 0x0500
(c'est le mieux)
cs_Manson
Messages postés137Date d'inscriptionlundi 17 décembre 2001StatutMembreDernière intervention30 septembre 2004 21 juil. 2003 à 11:16
salut,
moi je dirais que tu initialise la dll donc avec un WSAStartup,
ensuite tu initialiase la socket du "server", tu cree un nouveau thread dans lequel tu fais tourner un select (c'est mieux, 'fin je trouve) et enfin en fonction des FD tu transcrit le msg.
cs_kawito
Messages postés24Date d'inscriptiondimanche 20 juillet 2003StatutMembreDernière intervention13 décembre 2005 21 juil. 2003 à 21:26
Salut,
voici ce que j'ai fais :
j'ai cree une class socket (socketReseau)
une class serveur qui derive de socketReseau
une class client qui derive de socketReseau egalement
la class serveur possede une liste dynamique de type generic ici la liste est du type socketReseau, cette liste correspond aux clients qui se connecterons.
le type Liste est une liste generic ,on peut y acceder avec un iterateur ou comme un tableau Liste[0].
pour ce qui est des buffers d'entre sortie des sockets (voir class socketReseau, j'ai prevu 2 buffers un pour l'entree et un pour la sortie.
je ne sais pas encore ce qui est le mieux au niveau des buffers ,ais je fais le bon choix ?
peut etre q'un seul buffer suffirais ,et pourrais etre sur un void* !!?
chaque buffer a une taille de 1024 (voir constante)
voici ce que fais mon serveur:
initialiser winsock
demarrer serveur
ecouter
accept (bloque !, il attend une connexion d'un client, donc pas cool !)
si client accepte,
le serveur attend le nom du client
recv (bloque aussi !)
le serveur envoie son nom au client
send
voici ce que fais mon client:
initialiser winsock
connecter
le client envoie son nom au serveur
send
le client attend le nom du serveur
recv (bloque !)
je vous passe les detaille de la saisie au clavier du port de l'adresse ip du serveur, du nom du client et du nom du serveur !
BREF : mon client se connecte correctement a mon serveur
ils echangent leurs nom ,et je fais afficher l'adresse ip de chacun a l'ecran
pour l'instant le serveur ne gere q'un seul client (voir constructeur de la class serveur.(la liste n'a q'un socket)
l idée du thread, j'y ais bien pensais ,mais j'ai pas tout compris comment faire,declarer un thread et comment l'implenter dans mon programme...
vu mon architecture quel est la meilleur methode, et ne pas oublier que j'utilise GLUT et c++ en console application
voici mon MAIN : int main(int argc, char** argv)
{
int idFenetre; // Identifiant de la fenêtre principale
/*** Initialisations ***/
glutInit(&argc, argv); // Initialise la bibliothèque GLUT
initialiserFenetre(&idFenetre);
initialiserOpenGL();
initialiserVariables();
/*** Boucle principale ***/
glutReshapeFunc(rafraichir);
glutIdleFunc(callBackFonction);
glutDisplayFunc(afficher);
glutMouseFunc(souris);
glutKeyboardFunc(clavier);
glutMainLoop();
return 0;
}
/*** Initialiser la version de Winsock et demarre Winsock ***/
int initialiserWinsock(void);
#endif
/************ socket.h ****************/
/**************************/
/* MA CLASSE SERVEUR
/**************************/
le type Liste est une liste dynamique sur un type quelconque
elle derive de socketReseau
int connexionServeur(char* adresseIPServeur, unsigned short & port, int socType, int socFam);
int Connecter();
void arreterClient();
};
#endif
/************ serveur.h ****************/
voici un aperçu du serveur.cpp
/*** Destructeur ***/
serveur::~serveur()
{
int k = 0;
int erreur = 0;
erreur = closesocket(listeSocketsClients[k].lireSocketConnexion());
if (erreur == SOCKET_ERROR)
{
cerr << "Erreur Fermeture Socket Client pendant l'arret du serveur :" << WSAGetLastError() << endl;
}
WSACleanup(); // arret de winsock
listeSocketsClients.detruireListe();
}
int serveur::demarrerServeur(unsigned short & port, int socType, int socFam)
{
int erreur = 0;
this -> ecrireFamilleSocketAdresseIn(socFam);
this -> ecrireSocketType(socType);
this -> ecrireAdresseSocketAdresseInLocal();
this -> ecrirePortSocketAdresseIn(port);
this -> creerSocket();
this -> bindSocket();
if (this -> lireSocketConnexion() != INVALID_SOCKET)
{
cout << "SOCKET SERVEUR CREE AVEC SUCCES" << endl;
cout << "ADRESSE : " << lireAdresseSocketAdresseIn() << endl;
cout << "PORT : " << lireSocketAdresseIn().sin_port << endl;
return(0);
}
else
{
cerr << "ERREUR LORS DE LA CREATION DU SOCKET SERVEUR" << endl;
erreur = closesocket(this -> lireSocketConnexion());
if (erreur == SOCKET_ERROR)
{
cerr << "Erreur fermeture socket serveur lors du demarrage suite a une erreur a la creation : " << WSAGetLastError() << endl;
WSACleanup(); // arret de winsock
return(INVALID_SOCKET);
}
return(INVALID_SOCKET);
}
return(0);
}
/*** Mise en ecoute du serveur ***/
int serveur::ecouter(void)
{
if (listen(this -> lireSocketConnexion(), 0) == 0)
{
cout << "PASSAGE EN ECOUTE DU SERVEUR REUSSI" << endl;
return(0);
}
else
{
cerr << "ERREUR LORS DU PASSAGE EN ECOUTE DU SERVEUR : " << WSAGetLastError() << endl;
}
return(SOCKET_ERROR);
}
/*** Attendre la connexion du client ***/
int serveur::attenteConnexionsClients(void)
{
int tailleAdresse = 0;
cbestern
Messages postés25Date d'inscriptionjeudi 19 décembre 2002StatutMembreDernière intervention17 novembre 2003 16 août 2003 à 13:41
en quelques mots pour les thrad:
définir 2 handle, 1 pour le thread et un pour l'évenement
(un évenement est soit signer soit non signer comme un bolleen)
HANDLE HandTread= NULL;
HANDLE HandEvent=NULL;
//définit ta fonction thread (qui se nome ici FonctionThread)
DWORD FonctionThread(LPVOID)
{
//ici il boucle juqu'a l'arriver de l'évement
while(WaitForSingleObject(HandEventEm,0)!=WAIT_OBJECT_0)
{
//fait Ce que tu veut!!!
}
}
//pour le lancer
void StartThread()
{
assert(!HandTread);
assert(!HandEvent);
HandEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
DWORD ThreadIDRe;
//c ici même qu'il crée le thread
HandTread = CreateThread(NULL,0,FonctionThread,NULL,0,&ThreadIDRe);
}
//et pour l'arrêter:
void Stopthread()
{
assert(HandTread);
assert(HandEvent);
//signale l'évenement pour le faire sortir de sa boucle
SetEvent(HandEvent);
WaitForSingleObject(HandEvent,INFINITE);
CloseHandle(HandTread);
CloseHandle(HandEvent);
HandTread = NULL;
HandEvente = NULL;
}
Bon ça c pour une utilisation normale, juste un petit truc, il ne faut pas que ton programme finisse avant ton thread.
j'espere avoir été assez clair.
Sinon regarde les exemples de client serveurs, ça pourrais t'aider
Vous n’avez pas trouvé la réponse que vous recherchez ?
kwisatz_haderach
Messages postés5Date d'inscriptionmardi 23 décembre 2003StatutMembreDernière intervention 3 janvier 2004 3 janv. 2004 à 14:16
Bonjour,
je fais le meme programme que toi : jeu openGL/C++ mais en utilisant DirectX pour l'input et l'audio (en prévision de rester sous Windows comme OS)
Si tu veux rajouter la fonctionnalité réseau, il faut créer une thread spécial réseau...
Le serveur possède 2 threads :
- ca boucle principal (thread SERVER_MAIN ) où il écoute, dispatche et envoie les informations aux sockets connectés
- une autre thread WAIT_CONNECTION qui s'occupe juste d'accepter les connections pour les ajouter au tableau des connectés.
Théoriquement dans la plupart des jeux que nous connaissons, la thread WAIT_CONNECTION est disponible qu'au moment où par exemple dans un wargame, on crée la salle et les autres rejoignent. Ensuite pendant le jeu, aucune connexion n'est souvent permise mais rien ne t'empeche de le faire comme tu le désires.
Pour t'expliquer les thread, je sais pas si tu aimes les articles en anglais mais voici la source que je me sers pour créer mes threads.. c'est une classe que je n'ai pas modifié dont je fais hérité mes classes thread comme networkThread ou encore gamecoreThread.... totalement compatible application dos par contre ce n'est pas cross-plateformable (ca existe comme mot ???) puisque sous unix/linux on utilise des commandes C systèmes pour créer les threads (enfin, je devrais dire "processus")
J'espère t'avoir un peu aider dans ta recherche...