IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

utilisation de la primitive socket


Sujet :

Réseau C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 189
    Par défaut utilisation de la primitive select()
    Bonjour tout le monde,

    j'ai un petit souci avec l'utilisation de la primitive select() des sockets.

    J'aimerais créer un serveur qui recoit des lignes de textes de plusieurs clients.

    Pour le moment j'arrive à me connecter avec un seul client. Les clients suivants ne sont pas acceptés par le serveur et j'ai un doute sur mon utilisation de select()

    Est ce que vous pourriez vérifier si je l'utilise bien ? Bonne soirée tout le monde.

    Voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    	//ON CREER LA SOCKET
    	if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))<0)
    	{
    		perror("erreur création socket") ;
    		exit(-4) ;
     
    	}
    	printf("Serveur TALK lancé sur le port %s \n", argv[1]) ;
     
    	//ON LIE LA SOCKET A LA STRUCTURE SOCKADDR
    	if(bind(s,(struct sockaddr *) &serv,sizeof(serv))<0)
    	{
    		perror("erreur socket") ;
    		exit(-5) ;
    	}
     
     
     
    	//ON LIMITE LE NOMBRE DE CONNEXION A 5
    	if(listen(s,5)<0)
    	{
    		perror("erreur listen") ;
    		exit(-6) ;		
    	}
     
    	while(1)
    	{
    		if ((a[nb] = accept(s,(struct sockaddr *)&client,&lg))==-1)
    		{
    			perror("erreur accept") ;
    			exit(-7) ;
    		}
    		else
    		{
    			printf("client accepté\n") ;
    			FD_SET(a[nb], &readfds) ;
    			nb++ ;
     
    		}
     
     
     
    		fd_set readfds2 = readfds ;
    		nr = select(nfds, &readfds2,0,0,0) ;
     
     
    		for(k=0 ; k<nb ; k++)
    		{
    			if(FD_ISSET(a[k],&readfds2))
    			{
    			//printf("client numero %d\n", k) ;
     
    			while(read(a[k],&buf, 1)>0)
    			write(1,&buf,1) ;
     
    			}
    		}
     
     
     
    	}

  2. #2
    Membre émérite Avatar de crocodilex
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    697
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 697
    Par défaut
    Le problème est que "accept" et "read" sont tout deux bloquants.
    Dans ton exemple, "select" est en attente uniquement sur les sockets des clients déjà connectés. Ce qu'il faut c'est rajouter le descripteur de la socket principale dans l'ensemble readfds. Une fois en attente avec le "select", il ne restera plus qu'à faire le tri des clients déjà connectés et ceux qui essayent de se connecter.
    J'ai repris ton code en essayant d'appliquer l'explication que je viens de donner en déplaçant juste tes blocs.
    Bien entendu, ce code n'est pas parfait. Je te laisse le soin de l'améliorer.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
       //ON CREER LA SOCKET
       if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))<0) 
       {
          perror("erreur création socket") ;
          exit(-4) ;
       }
       printf("Serveur TALK lancé sur le port %s \n", argv[1]) ;
     
       //ON LIE LA SOCKET A LA STRUCTURE SOCKADDR
       if(bind(s,(struct sockaddr *) &serv,sizeof(serv))<0) 
       {
          perror("erreur socket") ;
          exit(-5) ;
       }
     
       //ON LIMITE LE NOMBRE DE CONNEXION A 5
       if(listen(s,5)<0) 
       {
          perror("erreur listen") ;
          exit(-6) ;
       }
     
       /* On ajoute le FD de la socket principale dans l'ensemble readfds */
       nb = 0;
       a[nb++] = s;
       FD_SET(s, &readfds);
     
       while(1) 
       {
          fd_set readfds2 = readfds ;
          /* On attends qu'un descripteur soit actif */ 
          if ( select(nfds, &readfds2,0,0,0) == -1 ) 
          {
             perror("erreur select") ;
             exit(1) ;
          }
     
          for(k=0 ; k<nb ; k++) 
          {
             if(FD_ISSET(a[k], &readfds2)) 
             {
                if( a[k] == s) /* Est-ce que c'est le FD de la socket principale ? */
                {
                   /* Un client tente de se connecter */
                   if ((a[nb] = accept(s,(struct sockaddr *)&client,&lg)) == -1)  
                   {
                      perror("erreur accept") ;
                      exit(-7) ;
                   }
                   else 
                   {
                      printf("client accepté\n") ;
                      FD_SET(a[nb], &readfds) ; /* Ajouter le nouveau FD dans l'ensemble readfds */
                      nb++ ;
                   }
                }
                else   /* C'est un client qui envoi des donnees */
                {
                   while(read(a[k],&buf, 1)>0)
                   write(1,&buf,1) ;
                }
             }
          }
       }
    PS : En cherchant bien dans ce forum tu trouveras un topic concernant cette astuce.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 189
    Par défaut
    Voili voilà, j'ai avancé dans mon code. Par contre j'ai un souci vu que le serveur n'accepte qu'un seul client. Il en accepte un deuxieme si le premier n'a encore rien écris. J'ai beau cherché je ne trouve pas. Voici mon nouveau code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    #include <stdio.h>
    #include <stdlib.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <inttypes.h>
    #include <fcntl.h>
    #include <sys/time.h>
    #include <string.h>
    #include <sys/select.h>
     
    main(int argc, char ** argv)
    {
     
    	//DECLARATIONS DE VARIABLES
    	struct sockaddr_in serv ;
    	struct sockaddr_in client ;
    	int port ;
    	int s ;
    	int a[50] ;
    	char buf ;
    	int lg = sizeof(client) ;
    	int reponse ;
    	int dfichier ;
    	int nb ;
    	int nr ;
    	int k ;
    	int j ;
    	fd_set readfds ;
    	int nfds ;
    	int max ;
    	int continu ;
     
     
    	serv.sin_family = AF_INET ;
    	sscanf(argv[1], "%d" ,&port ) ;	
    	serv.sin_port = htons(port) ;
    	serv.sin_addr.s_addr = htonl(INADDR_ANY) ;
     
     
    	//ON CREER LA SOCKET
    	if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))<0)
    	{
    		perror("erreur création socket") ;
    		exit(-4) ;
     
    	}
    	printf("Serveur TALK lancé sur le port %s \n", argv[1]) ;
     
    	//ON LIE LA SOCKET A LA STRUCTURE SOCKADDR
    	if(bind(s,(struct sockaddr *) &serv,sizeof(serv))<0)
    	{
    		perror("erreur socket") ;
    		exit(-5) ;
    	}
     
     
     
    	//ON LIMITE LE NOMBRE DE CONNEXION A 5
    	if(listen(s,5)<0)
    	{
    		perror("erreur listen") ;
    		exit(-6) ;		
    	}
     
    	//ON MET EN PLACE UN TABLEAU QUI CONTIENDRA TOUS LES DESCRIPTEURS
    	nb=0 ;
    	a[nb]=s ; 
    	nb++ ;
    	FD_ZERO(&readfds) ;
    	FD_SET(s, &readfds) ;
     
     
    	while(1)
    	{	
     
    		for(j=0, max=a[0] ; j<nb;j++)
    		{
    			if(a[j]>max)
    			max=a[j] ;		
    		}
     
    		nfds=max+1 ;
    		fd_set readfds2 = readfds ;
     
     
     
    		if(select(nfds, &readfds2,0,0,0)==-1)
    		{
    			perror("erreur select") ;
    			exit(-9) ;
    		}
    		else	
    		for(k=0; k<nb ; k++)
    		{
     
     
    			if(FD_ISSET(a[k],&readfds2))
    			{
     
    				if(a[k]==s)
    				{
     
    					if ((a[nb] = accept(s,(struct sockaddr *)&client,&lg))==-1)
    					{
    						perror("erreur accept") ;
    						exit(-7) ;
    					}
    					else
    					{
    						printf("client accepté\n") ;
    						FD_SET(a[nb], &readfds) ;
    						nb++ ;
     
     
    					}
     
     
    				}
    				else
    				{	
    					while(read(a[k],&buf, 1)>0)
    					write(1,&buf,1) ;
    				}	
    			}
    		}
     
     
    	}
    	close(s) ;
     
     
     
    }

Discussions similaires

  1. Réponses: 1
    Dernier message: 25/05/2013, 18h25
  2. Utilisation de la librairie socket.io
    Par thomas_deblock dans le forum NodeJS
    Réponses: 0
    Dernier message: 13/07/2011, 14h19
  3. [c#] utilisation de System.Net.Socket
    Par TERRIBLE dans le forum Framework .NET
    Réponses: 1
    Dernier message: 21/12/2009, 09h35
  4. Réponses: 3
    Dernier message: 13/06/2008, 11h55
  5. utilisation des sockets sous windows
    Par Tupac dans le forum Réseau
    Réponses: 2
    Dernier message: 21/12/2002, 18h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo