Connection client serveur avec MFC

Résolu
Spiffou Messages postés 100 Date d'inscription jeudi 1 avril 2004 Statut Membre Dernière intervention 9 juin 2014 - 8 nov. 2004 à 22:19
Spiffou Messages postés 100 Date d'inscription jeudi 1 avril 2004 Statut Membre Dernière intervention 9 juin 2014 - 8 août 2005 à 18:30
Bonjour à tous,
j'avance petit à petit dans la programmation socket, mais je suis confronté à une nouvelle difficulté et j'ai une ou deux question sans réponse...

mon but est de developper un jeu dans lequel on peut s'affronter à 2 en LAN. Il n'y aura pas de fort trafic réseau. je cherche cependant à créer une interface client serveur afin d'échanger des données sur l'etat des 2 joueurs, d'ou mes questions:

1- dans mon systeme l'utilisateur doit pouvoir choisir d'etre client ou serveur, mais est il necessaire pour celui qui joue le role du serveur d'avoir un client qui se connecte à lui même pour participer aux échanges (à mon avis non, mais je ne m'y connais pas trop...)

2- j'ai vu dans des programmes l'utilisation massive de threads à tel point que l'on utilisait plus le support MFC est ce que c'est recommandé ou pas?. je m'explique, dans mon appli j'utilise pour la gestion d'évenements:
void CRoomDlg::OnConnetionClient()
et j'ai vu dans d'autres progs la creation d'un thread qui fait l'analyse évenementielle:
LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_INITDIALOG:
hDlg = hWnd;
SetClassLong(hWnd, GCL_HICON, (LONG) LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1))); //Permet de charger l'icone
break;

case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_LISTEN:
char tBuff[6];
int PORT;

GetDlgItemText(hWnd,IDC_PORT,tBuff,5);
PORT = atoi(tBuff);

CListen(PORT);
break;

...
...
laquelle de ces 2 solutions est la meilleure et pourquoi??

3- enfin ma derniere question, en rapport avec l'affreux bout de code ci dessous. j'ai crée un projet MFC AppWizard sur VC++6 et lors de l'execution du code pour les évenements creation serveur et connection client, le prog se bloque(j dois quitter le prog avec fin de tache) et rien ne se passe alors que mon code de connection me semble correct...
si qqun sait pkoi il m'aiderait bien...

merci à tous ceux qui auront le courage de me lire jusque là, si jamais ils ont maintenant le courage pour une réponse ca serait sympa...

//
// code
//

// Définition des variables Globables :
//-------------------------------------
SOCKET C_socket; // socket Client pour emission/reception sur le reseau
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
SOCKADDR_IN C_adresse; // adresse du client

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

void CRoomDlg::OnConnetionClient()
{
int Ret;
WSADATA WSAData;

// initialisation de Winsock version 2.2
//--------------------------------------
if ((Ret = WSAStartup(MAKEWORD(2,2), &WSAData)) != 0)
{
MessageBox("ERREUR :WSAStartup a echoue","CLIENT",MB_ICONSTOP);

return;
}

// Création du socket client de communication
// sur le reseau
//-------------------------------------------
C_socket = socket( AF_INET, // famille d'adresse du protocol (ici IPv4)
SOCK_STREAM, // type de socket du protocol (ici TPC/IP)
0); // protocol utilisé (ici TCP/IP)

// recuperation de l'adresse ip du serveur en notation point
//----------------------------------------------------------
char ipbuff[16];
GetDlgItemText(IDC_IPSERV,ipbuff,16);

// remplissage de la structure d'adressage winsock
// pour les communication reseau en IPv4
//------------------------------------------------
C_adresse.sin_family = AF_INET;
C_adresse.sin_addr.s_addr = inet_addr(ipbuff);
C_adresse.sin_port = htons(N_port);

// connection du socket sur le reseau
// avec les paramtres definis precdements
//----------------------------------------
if (connect(C_socket,(SOCKADDR*) &C_adresse,sizeof(C_adresse)) == SOCKET_ERROR)
{
MessageBox("ERREUR :connection socket a echoue","CLIENT",MB_ICONSTOP);
WSACleanup();
return ;
}
else
{
MessageBox("Connection OK","CLIENT",MB_ICONINFORMATION);
}

// Reception de données sur socket
//--------------------------------
char buffer[255];
recv( C_socket, // socket sur lequel on recoit
buffer, // buffer de reception
sizeof(buffer), // taille du buffer
0); // flag (dans notre cas tjs 0)

// affichage des données recues
//-----------------------------
SetDlgItemText(IDC_CHAT,buffer);

/*
//Initialisation de WSAAsyncSelect
if(WSAAsyncSelect(m_socket, hDlg, WM_SOCKET, FD_READ|FD_WRITE|FD_CONNECT) == SOCKET_ERROR)
{
MessageBox("ERREUR : WSAAsyncSelect a provoque une erreur","CLIENT",MB_ICONINFORMATION);
WSACleanup();
return ;
}
*/
}

void CRoomDlg::OnCreationServeur()
{
int Ret;
WSADATA WSAData;

printf("Serveur !\n");

// initialisation de Winsock version 2.2
//--------------------------------------
if ((Ret = WSAStartup(MAKEWORD(2,2), &WSAData)) != 0)
{
// NOTE: Since Winsock failed to load we cannot use
// WSAGetLastError to determine the specific error for
// why it failed. Instead we can rely on the return
// status of WSAStartup.
MessageBox("ERREUR :WSAStartup a echoue","SERVEUR",MB_ICONSTOP);
return ;
}

// Création du socket d'écoute sur le reseau
// (demande de connexion client)
//-------------------------------------------
L_socket = socket( AF_INET, // famille d'adresse du protocol (ici IPv4)
SOCK_STREAM, // type de socket du protocol (ici TPC/IP)
IPPROTO_TCP); // protocol utilisé (ici TCP/IP)

// remplissage de la structure d'adressage winsock
// pour les communication reseau en IPv4
//------------------------------------------------
S_adresse.sin_family = AF_INET;
S_adresse.sin_addr.s_addr = htonl(INADDR_ANY);
S_adresse.sin_port = htons(N_port);

// Bind du Socket
// association de l'adresse avec le socket
//----------------------------------------
if( bind( L_socket, (SOCKADDR *)&S_adresse, sizeof(S_adresse)) == SOCKET_ERROR)
{
MessageBox("ERREUR :bind a echoue","SERVEUR",MB_ICONSTOP);
closesocket(L_socket);
return ;
}

// mise à l'écoute de demande de connection client
// on utilise une file d'attente de 5 place
//------------------------------------------------
if (listen(L_socket,QUEUE) == SOCKET_ERROR)
MessageBox("ERREUR :listen on socket a echoue","SERVEUR",MB_ICONSTOP);

// accepation d'une nouvelle connexion quand elle arrive
// cette connexion se fait avec le socket de reception
// prevu a cet effet.
//------------------------------------------------------
char buff[255];
strcpy(buff,"Connexion avec le Serreur OK!\r\n\r\0");

// calcul de la taille du buffer d'adresse client
int taille_adr = sizeof(C_adresse);
if((S_socket = accept(L_socket, (SOCKADDR *)&C_adresse, &taille_adr)) != INVALID_SOCKET)
{
if (S_socket != SOCKET_ERROR)
{
// envoi des données, ici une chaine de caracteres
send( S_socket, // socket sur lequel on envoie
buff, // buffer d'envoi
strlen(buff)+1, // taille du buffer
0); // flag ( dans notre cas

MessageBox("ERREUR :listen on eeeeb socket a echoue","SERVEUR",MB_ICONSTOP);

}
else
MessageBox("ERREUR :listen on beeeesocket a echoue","SERVEUR",MB_ICONSTOP);
}



/*
if(WSAAsyncSelect(m_socket, hDlg, WM_SOCKET, FD_ACCEPT|FD_CLOSE|FD_READ|FD_WRITE) == SOCKET_ERROR)
{
CError(hDlg,"WSAAsyncSelect Error occured : ");
WSACleanup();
return false;
}*/

//Arrivée a ce stade les attentes de connexions se font a l'aide de FD_READ

}

2 réponses

YanisLiadon Messages postés 5 Date d'inscription mardi 1 février 2005 Statut Membre Dernière intervention 4 avril 2007
8 août 2005 à 13:15
Je ne suis pas sur de ce que je vais avancer, mais je crois me souvenir que les fonctions recv et send sont bloquantes.



C'est à dire que si tu lances recv, alors ton appli ne bougera plus tant qu'elle n'aura rien recu.



C'est peut être pour ca qu'on utilise souvent les thread... ca permet de ne pas figer l'appli tant que tu n'as rien recu ;)
3
Spiffou Messages postés 100 Date d'inscription jeudi 1 avril 2004 Statut Membre Dernière intervention 9 juin 2014 1
8 août 2005 à 18:30
oui le sujet est un peu vieux et j'ai déjà reglé mes pbs (merci à aardman entre autre).



néanmoins, merci pour la réponse, et oui en effet, la fonction recv est
bloquante alors que la fonction send n'occupe le processeur que le
temps de l'envoi si je me rappelle bien.

c'est pourquoi j'ai utilisé une programmation evenementielle avec wsa
event (pas facile d'ailleurs quand on part de zero...) et tout un tas
de threads

^^



bonne continuation et à bientôt pour de nouveaux problèmes

^^
0
Rejoignez-nous