bonjour à tous,
je voudrais votre avis sur la gestion des evenements sur les sockets.
je réalise une application (un jeu) qui doit communiquer sur un réseau local. j prévois donc d'utiliser 2 thread, un d'envoi et un de reception.
j'ai plusieurs pb:
- la gestion des evenement ne marche pas, en effet, je crée bien les evenements avec (WSACreateEvent) et je les assigne au socket (WSAEventSelect). par contre, le pb se situe j pense au niveau de l'attente d'evenement (WSAWaitForMultipleEvents) parce que le programme semble se bloquer à ce niveau.
- de plus, lors de la gestion du serveur, je ne vois pas comment gérer les evenements après acceptation de la connexion (accept) car il y a création d'un autre socket pour les communication.
(j'ai bien lu l'histoire dans laquelle on crée un tableau cf le livre conseillé par aardman qui est tres bien; mais j n'arrive pas à l'implémenter) j'ai donc choisi de créer un autre évenement sans faire tte l'histoire du tableau mais ca ne marche pas, le prog se bloque à nouveau sur WSAWaitForMultipleEvents.
- enfin rassurez moi, il m'a semble que d'utiliser la gestion de socket avec WSAWaitForMultipleEvents etait un bon choix, j'ai bon...??
Désolé pour la longueur du post, et pour ceux qui auront le courage de lire, merci beaucoup pour vos réponses.
//
// Voila le Code Client:
//
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char ** argv)
{
char buffer[250];
int N_port = 6566; // numero du port de communication
int QUEUE = 5; // taille de la file d'attente pour la connection sur le listen socket
SOCKET C_socket;
SOCKADDR_IN C_adresse; // adresse du client
WSAEVENT hEvent[1];
WSANETWORKEVENTS NetworkEvent;
printf("Chat Client\n");
// initialisation de la connection
C_socket = socket(AF_INET, SOCK_STREAM, 0);
if(C_socket == -1)
{
printf("ERREUR : echac de la création de socket\n");
}
C_adresse.sin_family = AF_INET;
C_adresse.sin_port = htons(N_port);
C_adresse.sin_addr.s_addr = inet_addr("127.0.0.1");
hEvent[0] = WSACreateEvent();
WSAEventSelect(C_socket, hEvent[0], FD_WRITE | FD_READ | FD_CONNECT | FD_CLOSE);
printf("Demande de connexion au serveur 127.0.0.1\n");
connect(C_socket, (sockaddr*)&C_adresse, sizeof(C_adresse));
// Boucle de gestion des evenements
while(true)
{
printf("Client Gestion Event\n");
memset(&NetworkEvent, 0, sizeof(NetworkEvent));
WSAWaitForMultipleEvents(1, hEvent, 0, WSA_INFINITE, 0);
WSAEnumNetworkEvents(C_socket, hEvent[0], &NetworkEvent);
if(NetworkEvent.lNetworkEvents & FD_CONNECT)
{
printf("Client Event Connect\n");
// erreur a la connexion
if(NetworkEvent.iErrorCode[FD_CONNECT_BIT])
{
printf ("ERREUR : Connexion error\n");
break;
}
// si connexion ok, envoi de la requete
}
if (NetworkEvent.lNetworkEvents & FD_WRITE)
{
printf("Client Event Write\n");
if (NetworkEvent.iErrorCode[FD_WRITE_BIT] != 0)
{
printf("FD_WRITE failed with error %d\n", NetworkEvent.iErrorCode[FD_WRITE_BIT]);
break;
}
// envoie de données
send(C_socket,
buffer,
sizeof(buffer),
0);
}
if(NetworkEvent.lNetworkEvents & FD_READ)
{
printf("Client Event Read\n");
// erreur a la connexion
if(NetworkEvent.iErrorCode[FD_READ_BIT])
{
printf ("ERREUR : Read error\n");
break;
}
// lecture de donnees sur le socket
recv(C_socket,buffer, sizeof(buffer), 0);
}
if(NetworkEvent.lNetworkEvents & FD_CLOSE)
{
printf("Client Event Close\n");
// verifie s'il ne reste plus rien a lire sur le socket
do
{
memset(&NetworkEvent, 0, sizeof(NetworkEvent));
WSAEnumNetworkEvents(C_socket, 0, &NetworkEvent);
if(NetworkEvent.lNetworkEvents & FD_READ)
{
if(NetworkEvent.lNetworkEvents & FD_READ)
{
// erreur a la connexion
if(NetworkEvent.iErrorCode[FD_READ_BIT])
{
printf ("ERREUR : Read error\n");
break;
}
// lecture de donnees sur le socket
recv(C_socket,buffer, sizeof(buffer), 0);
}
}
}
while(NetworkEvent.lNetworkEvents & FD_READ);
}
}
return 0;
}
//
// Voila le Code Serveur:
//
// serveur.cpp : Defines the entry point for the console application.
//
#include "string.h"
#include "stdio.h"
#include "conio.h"
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")
void accept(void);
int main(int argc, char* argv[])
{
char buffer[250];
SOCKET L_socket; // socket pour ecoute sur le reseau (listen)
SOCKET S_socket; // socket Serveur pour emission/reception sur le reseau
SOCKADDR_IN S_adresse; // adresse du serveur
int N_port = 6667; // numero du port de communication
int QUEUE = 5; // taille de la file d'attente pour la connection sur le listen socket
int Ret;
WSADATA WSAData;
WSAEVENT hEvent[2];
WSANETWORKEVENTS NetworkEvent,NewEvent;
printf("Chat Serveur !\n");
// initialisation de la connexion
if ((Ret = WSAStartup(MAKEWORD(2,2), &WSAData)) != 0)
{
printf("ERREUR :WSAStartup a echoue",Ret);
return (-1);
}
L_socket = socket( AF_INET,SOCK_STREAM,IPPROTO_TCP);
S_adresse.sin_family = AF_INET;
S_adresse.sin_addr.s_addr = htonl(INADDR_ANY);
S_adresse.sin_port = htons(N_port);
bind( L_socket,(SOCKADDR *)&S_adresse,sizeof(S_adresse));
// creation d'un evenement reseau
hEvent[0] = WSACreateEvent();
WSAEventSelect(L_socket, hEvent[0], FD_ACCEPT | FD_CLOSE);
listen(L_socket, QUEUE);
while(TRUE)
{
memset(&NetworkEvent, 0, sizeof(NetworkEvent));
WSAWaitForMultipleEvents(1, hEvent, 0, WSA_INFINITE, 0);
WSAEnumNetworkEvents(L_socket, hEvent[0], &NetworkEvent);
// Check for FD_ACCEPT messages
if (NetworkEvent.lNetworkEvents & FD_ACCEPT)
{
printf("Serveur Event Accept\n");
if (NetworkEvent.iErrorCode[FD_ACCEPT_BIT] != 0)
{
printf("FD_ACCEPT failed with error %d\n",NetworkEvent.iErrorCode[FD_ACCEPT_BIT]);
break;
}
// Accept a new connection, and add it to the
// socket and event lists
accept();
}
if (NetworkEvent.lNetworkEvents & FD_CLOSE)
{
printf("Serveur Event Close\n");
if (NetworkEvent.iErrorCode[FD_CLOSE_BIT] != 0)
{
printf("FD_CLOSE failed with error %d\n",NetworkEvent.iErrorCode[FD_CLOSE_BIT]);
break;
}
closesocket(S_socket);
}
}
// fermeture du socket
//--------------------
closesocket(S_socket);
closesocket(L_socket);
// liberation des ressources allouées pour la communication
//---------------------------------------------------------
if (WSACleanup() == SOCKET_ERROR)
{
printf("ERREUR : WSACleanup a echoue, erreur : %d\n", WSAGetLastError());
}
return 0;
}
void accept(void)
{
printf("Serveur ConneX Accept\n");
S_socket = accept(
L_socket,
NULL,
NULL);
// send de test
send(S_socket,
"ca marche",
9,
0);
hEvent[1] = WSACreateEvent();
WSAEventSelect(
S_socket,
hEvent[1],
FD_READ | FD_WRITE | FD_CLOSE);
while(true)
{
memset(&NewEvent, 0, sizeof(NewEvent));
WSAWaitForMultipleEvents(1, hEvent, 0, WSA_INFINITE, 0);
WSAEnumNetworkEvents(S_socket, hEvent[1], &NewEvent);
// Process FD_READ notification
if (NewEvent.lNetworkEvents & FD_READ)
{
printf("Serveur Event Read\n");
if (NewEvent.iErrorCode[FD_READ_BIT] != 0)
{
printf("FD_READ failed with error %d\n", NewEvent.iErrorCode[FD_READ_BIT]);
break;
}
// Read data from the socket
recv(S_socket,buffer, sizeof(buffer), 0);
}
// Process FD_WRITE notification
if (NewEvent.lNetworkEvents & FD_WRITE)
{
printf("Serveur Event Write\n");
if (NewEvent.iErrorCode[FD_WRITE_BIT] != 0)
{
printf("FD_WRITE failed with error %d\n", NewEvent.iErrorCode[FD_WRITE_BIT]);
break;
}
send(S_socket,
buffer,
sizeof(buffer),
0);
}
if (NewEvent.lNetworkEvents & FD_CLOSE)
{
printf("Serveur Event Close\n");
if (NewEvent.iErrorCode[FD_CLOSE_BIT] != 0)
{
printf("FD_CLOSE failed with error %d\n",NewEvent.iErrorCode[FD_CLOSE_BIT]);
break;
}
closesocket(S_socket);
}
}
}