cs_fraboulet
Messages postés37Date d'inscriptionmardi 8 juillet 2003StatutMembreDernière intervention27 avril 2006
-
24 avril 2006 à 15:37
cs_fraboulet
Messages postés37Date d'inscriptionmardi 8 juillet 2003StatutMembreDernière intervention27 avril 2006
-
25 avril 2006 à 09:48
Bonjour à tous,
J'ai une
question concernant winsock2, je souhaite faire un thread d'écoute de
sockets. Mais je souhaite pouvoir ajouter dynamiquement une socket dans
le pool de socket déjà existant.
J'ai fait le code suivant
(issu en grande partie de Sylvain MARECHAL -
sylvain.marechal1@libertysurf.fr) qui se contente de "lever" un event
pour déclencher une réaction (envoie de données ici, mais ce pourrait
être ajout d'une nouvelle socket en écoute).
Le problème est que le ResetEvent semble poser problème...car le WaitForMultipleEvents plante après.
// Ce programme créé 3 sockets :
// La première socket écoute le premier port de libre, la 2° se connecte
// dessus, ce qui crée donc une 3° socket.
//
Après avoir échangé un paquet de données, un event d'administration est
envoyé ce qui doit engendrer l'envoie d'un n ouveau paquet et lors de
la
// réception un nouvel event d'administration doit être généré...
//
/////////////////////////////////////////////////////////////////////////////
#include <winsock2.h>
#include <stdio.h>
#include <conio.h>
#define SOCKET_ERRNO WSAGetLastError()
/////////////////////////////////////////////////////////////////////////////
//
// LISTENFIRSTFREEPORT
/////////////////////////////////////////////////////////////////////////////
//
// DESCRIPTION
// --ListenFirstFreePort--
//
// Creation de la premiere socket qui ecoute le premier port
// de libre
//
// ARGUMENTS
// Argument1: int * pnPort
// RETOUR/RESULTAT
// static SOCKET
// REMARQUE
// Rev 09/12/2003
//////////////////////////////////////////////////////////////////////////////
static SOCKET ListenFirstFreePort( int * pnPort )
{
struct sockaddr_in addr;
int len = sizeof(addr);
SOCKET hSocket;
// 2° socket qui se connecte sur la premiere
ahSocket[1]= ConnectToPort(nListenPort);
rc = WSAEventSelect(ahSocket[1], ahEvents[1], FD_CONNECT );
if( rc == SOCKET_ERROR )
{
printf( "WSAEventSelect() error %d\n", SOCKET_ERRNO );
exit(1);
}
// On boucle
while (TRUE)
{
DWORD dwEvent;
WSANETWORKEVENTS NetworkEvents;
// On attend que quelquechose arrive.
// Typiquement, on va commencer par recevoir la connexion
// puis ensuite, on sera notifie pour lire les donnees
dwEvent = WSAWaitForMultipleEvents(4, ahEvents, FALSE, INFINITE, FALSE);
switch (dwEvent)
{
case WSA_WAIT_FAILED:
printf("WSAEventSelect: %d\n", WSAGetLastError());
break;
case WAIT_IO_COMPLETION:
case WSA_WAIT_TIMEOUT:
break;
default:
// On deduit la socket du numero d'evenement
dwEvent -= WSA_WAIT_EVENT_0;
// => hSocket = ahSocket[dwEvent];
if (FD_CONNECT & NetworkEvents.lNetworkEvents)
{
// La connexion est OK
printf( "FD_CONNECT ok (dwEvent=%d)\n", dwEvent );
// On va recevoir un paquet de donnee
rc = WSAEventSelect(ahSocket[dwEvent], ahEvents[dwEvent], FD_CLOSE | FD_READ );
if( rc == SOCKET_ERROR )
{
printf( "WSAEventSelect() error %d\n", SOCKET_ERRNO );
exit(1);
}
}
if (FD_CLOSE & NetworkEvents.lNetworkEvents)
{
// Seule la socket 2 va recevoir la notification de fermeture
printf( "FD_CLOSE ok (dwEvent=%d)\n", dwEvent );
printf( "press a key to exit\n" );
getch();
// On pourrait faire plus propre :-)
exit(0);
}
if (FD_READ & NetworkEvents.lNetworkEvents)
{
char szBuffer[256]; int cbRecv;
// Seule la socket 1 s'attend a recevoir un paquet de donnees
printf( "FD_READ ok (dwEvent=%d)\n", dwEvent );
// On lit le paquet
cbRecv = recv( ahSocket[dwEvent], szBuffer, sizeof(szBuffer) - 1, 0 );
if( cbRecv <= 0 )
{
printf( "recv() error %d\n", SOCKET_ERRNO );
exit(1);
}
// On ecrit ce paquet (On remet le 0 au cas ou le paquet
// ait ete coupe en 2 - je sais, ca n'arrivera jamais en local)
szBuffer[cbRecv] = 0;
printf( "socket %d : '%s'\n", dwEvent, szBuffer );
// Maintenant on lève un event d'administration
WSASetEvent(ahEvents[3]);
}
if (FD_WRITE & NetworkEvents.lNetworkEvents)
{
char szBuffer[256]; int cbBuffer, cbSend;
// il doit s'agir de la 2° socket, puisque c'est la seule
// qui demande quand elle pourra ecrire.
// Comme on est la, c'est qu'on doit pouvoir ecrire
printf( "FD_WRITE ok (dwEvent=%d)\n", dwEvent );
// On envoie la chaine avec le 0 de fin
cbBuffer = sprintf( szBuffer, "Coucou depuis la socket %d\n", dwEvent );
cbSend = send( ahSocket[dwEvent], szBuffer, cbBuffer + 1, 0 );
// En socket non bloquante, il est possible que cbSend < cbBuffer
// en particulier en charge. Il faut donc verifier cela et buffeuriser
// au cas ou. Ici, c'est un exemple donc on ne le fait pas
if( cbSend != cbBuffer + 1 )
{
printf( "send() error %d\n", SOCKET_ERRNO );
exit(1);
}
}
if (FD_ACCEPT & NetworkEvents.lNetworkEvents)
{
struct sockaddr_in addr;
int len;
// On doit avoir dwEvent=0
printf( "accept ok (dwEvent=%d)\n", dwEvent );
len = sizeof( addr );
// On accepte la connexion (3° socket => ahSocket[2] )
ahSocket[2] = accept(ahSocket[dwEvent], (struct sockaddr *)&addr, &len);
// On demande à etre prevenu qd on pourra ecrire de la
// donnee sur cette nouvelle socket
rc = WSAEventSelect(ahSocket[2], ahEvents[2], FD_CLOSE | FD_WRITE );
if( rc == SOCKET_ERROR )
{
printf( "WSAEventSelect() error %d\n", SOCKET_ERRNO );
exit(1);
}
}
}
}
}
WSACloseEvent( ahEvents[0] );
WSACloseEvent( ahEvents[1] );
WSACloseEvent( ahEvents[2] );
}
cs_AlexN
Messages postés694Date d'inscriptionlundi 5 décembre 2005StatutMembreDernière intervention 8 janvier 201419 24 avril 2006 à 21:23
Juste une question, comme je n'ai pas trop compris ce que tu voulais faire.
Je m'attendais à voir une alternance paquet de service - paquet admin - paquet de service - paquet admin - etc... Mais en fait, la socket ne recoit que des paquets admin (sauf 1 de service). C'était ce que tu voulais ?
cs_fraboulet
Messages postés37Date d'inscriptionmardi 8 juillet 2003StatutMembreDernière intervention27 avril 2006 25 avril 2006 à 09:48
En fait,
Je souhaite faitre un ordonnaceur réseau que l'on puisse interrompre pour :
1 - Ajouter une socket à scrupter
2 - Envoyer une donnée.
Je souhaite que l'interruption soit également événementielle (event d'admin) => je ne veux surtout pas d'un WaitForMultipleEvents avec timeout qui poll à chaque fois pour déterminer si une donnée doit être envoyée ou si une nouvelle socket doit être scruptée.
Le code que j'ai donné ici n'est qu'un test pour voir si il était possible de sortir du WaitForMultipleEvents autrement qu'avec un événement "réseau".
Comme tu le dis, l'objectif en définitive est bien d'avoir une alternance paquet de service (réception de données) / paquet admin (avec bcp plus de paquet de données par ailleurs).