begin process at 2012 05 29 21:52:29
  Trouver un code source :
 
dans
 
Accueil > Forum > 

Archive C/C++

 > 

Archives

 > 

Réseau / Internet

 > 

Problème ResetEvent Winsock2


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

Problème ResetEvent Winsock2

dimanche 23 avril 2006 à 23:03:34 | Problème ResetEvent Winsock2

fraboulet

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;

    // Premiere socket
    hSocket = socket( PF_INET, SOCK_STREAM, 0 );
    if( hSocket == INVALID_SOCKET )
    {
        printf( "socket() error %d\n", SOCKET_ERRNO );
        exit(1);
    }

    // On ecoute le premier port de libre
    addr.sin_family = AF_INET ;
    addr.sin_addr.s_addr = htonl (INADDR_ANY);
    addr.sin_port = htons ((unsigned short)*pnPort ); // 0 = le premier de libre
    if ( bind( hSocket, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR )
    {
        printf( "bind() error %d\n", SOCKET_ERRNO );
        exit(1);
    }
    if ( listen( hSocket, 100) == SOCKET_ERROR )
    {
        printf( "listen() error %d\n", SOCKET_ERRNO );
        exit(1);
    }

    // On recupere la valeur du port
    if( getsockname( hSocket, (struct sockaddr *)&addr, &len) == SOCKET_ERROR )
    {
        printf( "listen() error %d\n", SOCKET_ERRNO );
        exit(1);
    }
    *pnPort = ntohs( addr.sin_port );

    return hSocket;
}



/////////////////////////////////////////////////////////////////////////////
//
//        CONNECTTOPORT
/////////////////////////////////////////////////////////////////////////////
//
//  DESCRIPTION
//       --ConnectToPort--
//
//    Creation de la 2° socket qui va se connecter sur la premiere
//
//  ARGUMENTS
//        Argument1: int nPort
//  RETOUR/RESULTAT
//        SOCKET
//  REMARQUE
//  Rev 09/12/2003
//////////////////////////////////////////////////////////////////////////////
SOCKET ConnectToPort( int nPort )
{
    struct sockaddr_in addr;
    SOCKET hSocket;
    u_long arg; int err;

    // Deuxieme socket
    hSocket = socket( PF_INET, SOCK_STREAM, 0 );
    if( hSocket == INVALID_SOCKET )
    {
        printf( "socket() error %d\n", SOCKET_ERRNO );
        exit(1);
    }

    // On passe en mode non bloquant
    arg = 1;
    err = ioctlsocket( hSocket, FIONBIO, &arg );
    if( err == SOCKET_ERROR )
    {
        printf( "ioctlsocket() : Error n %d\n", SOCKET_ERRNO );
        exit(1);
    }

    // On se connecte en local
    addr.sin_family = AF_INET ;
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_port = htons ((unsigned short)nPort );
    if( connect( hSocket, (struct sockaddr *)&addr, sizeof(addr) ) == SOCKET_ERROR )
    {
        // En mode non bloquant, on aura jours l'erreur
        // WSAEWOULDBLOCK qui n'en est pas une
        if( SOCKET_ERRNO != WSAEWOULDBLOCK )
        {
            printf( "connect() error (%d)\n", SOCKET_ERRNO );
            return -1;
        }
    }

    return hSocket;
}



void main()
{
    WSADATA stack_info;
    SOCKET ahSocket[4];
    WSAEVENT ahEvents[4];
   
    int rc;
    int nListenPort = 0;

    // On initialise Winsock
    WSAStartup(MAKEWORD(2,0), &stack_info) ;

    // 3 evenements pour les 3 socket
    ahEvents[0] = WSACreateEvent();
    ahEvents[1] = WSACreateEvent();
    ahEvents[2] = WSACreateEvent();

    // 1 evenement d'administration (pour ajouter une socket en écoute par exemple)
    ahEvents[3] = WSACreateEvent();

    // Premiere socket qui ecoute
    ahSocket[0] = ListenFirstFreePort( &nListenPort );
    rc = WSAEventSelect(ahSocket[0], ahEvents[0], FD_ACCEPT );
    if( rc == SOCKET_ERROR )
    {
        printf( "WSAEventSelect() error %d\n", SOCKET_ERRNO );
        exit(1);
    }

    // 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 (dwEvent == 3) // Event d'administration
            {
                WSAResetEvent(ahEvents[3]);
                char szBuffer[256]; int cbBuffer, cbSend;
                printf( "FD_WRITE ok (dwEvent=%d)\n", dwEvent );
                cbBuffer = sprintf( szBuffer, "Coucou depuis la socket %d\n", dwEvent );
                cbSend = send( ahSocket[1], szBuffer, cbBuffer + 1, 0 );
                if( cbSend != cbBuffer + 1 )
                {
                    printf( "send() error %d\n", SOCKET_ERRNO );
                    exit(1);
                }
                continue;
            }
            else
            {
                WSAEnumNetworkEvents(ahSocket[dwEvent], ahEvents[dwEvent], &NetworkEvents);

                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] );
}



Cette discussion est classée dans : printf, socket, error, addr, dwevent


Répondre à ce message

Sujets en rapport avec ce message

Winsock2 WASEvents... [ par fraboulet ] Bonjour à tous,J'ai une question concernant winsock2, je souhaite faire un thread d'écoute de sockets. Mais je souhaite pouvoir ajouter dynamiquement Visual C++ 6 : error LNK2001: unresolved external symbol [ par gros_landais ] Lorsque je link ce server TCP/IP avec Visual C++ 6.0 j'ai les erreurs de link suivante :--------------------Configuration: all - Win32 Debug---------- pb de redirection [ par grums45 ] bonjour je suis étudiant en informatique, dans le cadre d'un stage j'ai une application réseau à réaliser en c. Mon problème est le suivant suite à la connexion database [ par callaghan1981 ] j ai un petit problemeje me connecte a la base de donnee acces..mais il n arrete pas de me retourner un error comme quoi ADOje sais pas quoi est peut Envois et reception de commande [ par t0Xic_h ] SalutVoici mon code source .La connection entre le client et le serveur se passe bien, mais je n'ai pas su ecrirele code qui me permettera d'envoyer l Connexion SOCKET_ERROR [ par fredsor ] Salut a tous,Je réalise un ptit programme au sein duquel je me connecte a un serveur distant, afin de récupérer via une methode GET des informations n Requetes serveur cs 1.6 [ par Mini92 ] En fait, j'essaye d'envoyer des requêtes sur mon serveur cs mais je n'obtiens aucun retour.Voilà le code si quelqu'un peu m'aider svp#include #include passage de structure a un thread [ par anthonycosson ] bijour tout le monde g un pb qui me blocje voudrai savoir comment passer une structure a AfxBeginThread et récupéré les donner précédement enregistrer Socket et dev c++ [ par CCJ ] Bonjour. JE tente de creer un programme de dialogue par socket en c++ via dev c++ et dés le debut je rencontre un probleme , des references semblent m


Nos sponsors


Sondage...

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,342 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales