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 :

identification des sockets


Sujet :

Réseau C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 29
    Par défaut identification des sockets
    Bonjour, je suis en train de faire un petit chat en C en utilisant les sockets sous Linux.
    J'en suis a essayé de renvoyer à tous les clients connectés un message reçu par le serveur. Pour cela, j'ai le descripteur de socket de chaque client dans le serveur. Je me sers de ses descripteurs pour communiquer avec tous les clients (enfin j'aimerais pour le moment).
    Voici le code du serveur :
    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
      listen(sd,MAXCLIENT);
      ladcour=sizeof(adclcour);
      for(;;)
        {
          if((nsd=accept(sd,(struct sockaddr*)&adclcour,(socklen_t*)&ladcour))<0)
    	{
    	  perror(">>Probléme avec accept");
    	  exit(1);
    	}
          printf("nsd :: %d\n",nsd);
      /* Récupération du nom du client */
          if(cherche(adclcour.sin_addr.s_addr,liste_cl,nb_client)==-1)
    	{
    	  printf("traitement nom\n");
    	  FD_SET(nsd,&ensemble);
    	  nsdbis=select(20,&ensemble,NULL,NULL,&timer);
    	  if(nsdbis)
    	    {
    	      read(nsd,buf,sizeof(buf));
    	      liste_cl[nb_client].ip=adclcour.sin_addr.s_addr;
    	      strcpy(liste_cl[nb_client].nom,buf);
    	      strcat(liste_cl[nb_client].nom," : ");
    	      liste_cl[nb_client].soc=nsd;
    	      nb_client++;
    	      printf("%s est %s\n",(char*)inet_ntoa(liste_cl[nb_client-1].ip),liste_cl[nb_client-1].nom);
    	      close(nsd);
    	    }
    	  else
    	    {
    	      write(nsd,"Resaisir le nom",strlen("Resaisir le nom"));
    	      close(nsd);
    	    }
    	  timer.tv_sec = 5;
    	}
          else
    	{
    	  if(fork()==0)
    	    {
    	      /* Traitement des messages */
    	      printf("Traitement messages\n");
    	      close(sd);
    	      nu_client=cherche(adclcour.sin_addr.s_addr,liste_cl,nb_client);
    	      printf("Client considéré :: %s\n",liste_cl[nu_client].nom);
    	      renvoi(liste_cl[nu_client].soc, liste_cl,nu_client,nb_client);
    	      exit(0);
    	    }
    	  else
    	    close(nsd);
    Pour le moment, j'arrive à communiquer avec n clients sur mon serveur. Mon serveur connait toutes les ips des clients.
    Voyez vous une autre façon de communiquer avec tous les clients, sans utiliser les threads. Je pense que mon problème est lié au stockage des descripteurs de socket et à ma gestion des sockets... Je n'ai pas réussi à trouver la solution à mon problème alors si vous pouvez m'éclairer un peu...

  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
    Citation Envoyé par asphalte
    [...]
    Voyez vous une autre façon de communiquer avec tous les clients, sans utiliser les threads.
    [...]
    Il y a une solution, c'est de passer ta socket en mode UDP et de faire du "broadcast".

  3. #3
    Membre éprouvé
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Par défaut
    Citation Envoyé par crocodilex
    Il y a une solution, c'est de passer ta socket en mode UDP et de faire du "broadcast".
    du broadcast? comment ça?

    pour moi la solution la plus simple est d'utiliser select dans un thread jusqu'a FD_SETSIZE clients.
    au dela, soit tu drop, soit tu fait un nouveau thread qui vas accepter encore FD_SETSIZE clients ...

    FD_SETSIZE vaut 1023 en principe sur les unixoïdes ... et une rumeurs dis que ça tourne autour de 128 pour les windowsoïdes.
    chiffres a confirmer!

    ensuite, soit tu definis un nombre max de clients qui pourrons se connecter (genre 4 * FD_SETSIZE) et tu fait un tableau d'entiers qui contiens tes sockets.
    soit tu fait une liste chainée et t'as plus de limite en nombre de clients.

  4. #4
    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
    Citation Envoyé par Dark_Ebola
    du broadcast? comment ça?
    Ce qu'il veut c'est envoyer un meme message à tout ses clients connectés. Le broadcast sert à ça non ? Ou alors je n'ai rien compris au problème...

  5. #5
    Membre chevronné Avatar de Lunixinclar
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 416
    Par défaut multiplexage asynchrone
    Salut, C'est sûr que le broadcast est l' alternative mais elle ne se fait pas en TCP. Et il faut tout ré-écrire. La modif ici est:
    Avant d'invoquer accept(), il faut copier le master (nommé ici "ensemble"), faire un select() sur la copie, pour faire une boucle sur tous les clients: FD_ISSET(n, &copie); détermine si un évènement est arrivé. Dans ce cas
    Si n = le socket qui écoute, alors un nouveau client se connecte c'est là qu'il faut accept().
    Sinon c'est que des données arrivent d'un client. Pour répercuter ce message vers tous les autres un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for(j = 0; j <= NBUSERS; j++)
    { 
      if (FD_ISSET(j, &master))
      { 
       if (j != listener)// && j != i) // ni lui ni moi
         if (send(j, strOUT, strlen(strOUT), 0) == -1) perror("send");
      }
    }
    suffit, pas besoin de fork.
    Ce n'est probablement pas clair mais tout est dans le titre.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 29
    Par défaut
    Pour le broadcast, comme ça été dit, ceci m'oblige à tout refaire ce qui ne m'enchante pas trop. Je préfèrerai éviter d'utiliser un thread pour l'écoute (c'est pour un TP et ça ne colle pas trop avec le sujet). Je vais donc tester la dernière solution, enfin essayer car je n'ai pas tout compris surtout au niveau du principe de faire une copie du "master".
    Je teste et je vous tiens au courant...

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 29
    Par défaut Résolu
    Finit le problème. En laissant ma socket de communication ouverte, le accept() me génère bien des descripteurs de socket diffèrents. Du coup, chaque client possède une ip et une socket propre à lui et de descripteur fixe. Je peux donc facilement communiquer avec chacun d'entre eux. A condition que tout soit bien synchronisé.
    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
      for(;;)
        {
          if((nsd=accept(sd,(struct sockaddr*)&adclcour,(socklen_t*)&ladcour))<0)
    	{
    	  perror(">>Probléme avec accept");
    	  exit(1);
    	}
          printf("nsd :: %d\n",nsd);
          if(cherche(adclcour.sin_addr.s_addr,liste_cl,nb_client)==-1)
    	{
    	  printf("traitement nom\n");
    	  FD_SET(nsd,&ensemble);
    	  nsdbis=select(20,&ensemble,NULL,NULL,&timer);
    	  if(nsdbis)
    	    {
    	      read(nsd,buf,sizeof(buf));
    	      liste_cl[nb_client].ip=adclcour.sin_addr.s_addr;
    	      strcpy(liste_cl[nb_client].nom,buf);
    	      strcat(liste_cl[nb_client].nom," : ");
    	      liste_cl[nb_client].soc=nsd;
    	      printf("%s est %s\n",(char*)inet_ntoa(liste_cl[nb_client-1].ip),liste_cl[nb_client-1].nom);
    	      write(liste_cl[nb_client].soc,"Connexion établie\n",strlen("Connexion établie\n"));
    	      nb_client++;
    	      //close(nsd);
    	    }
    	  else
    	    {
    	      write(nsd,"Resaisir le nom",strlen("Resaisir le nom"));
    	      close(nsd);
    	    }
    	  timer.tv_sec = 5;
    	  for(i=0;i<nb_client;i++)
    	    printf("%s utilise %d\n",liste_cl[i].nom,liste_cl[i].soc);
    	}
          else
    	{
    	  if(fork()==0)
    	    {
    	      /* Traitement des messages */
    	      printf("Traitement messages\n");
    	      close(sd);
    	      nu_client=cherche(adclcour.sin_addr.s_addr,liste_cl,nb_client);
    	      printf("Client considéré :: %s\n",liste_cl[nu_client].nom);
    	      renvoi(liste_cl[nu_client].soc, liste_cl,nu_client,nb_client);
    	      exit(0);
    	    }
    Merci pour vos réponses

  8. #8
    Membre chevronné Avatar de Lunixinclar
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 416
    Par défaut
    Quelle drole de cuisine.
    Enlever la boucle sur nb_client produit ce que tu voulais (à savoir, envoyer un msg à tous les clients)?
    La fonction cherche() est une fonction BSD? Est-elle vraiment nécessaire?
    Faire un fork par client donne de meilleures performances? Est-ce vraiment nécessaire?

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 29
    Par défaut
    >Je ne vois pas trop de quel boucle for tu parles. Si c'est de celle la ->
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	  for(i=0;i<nb_client;i++)
    	    printf("%s utilise %d\n",liste_cl[i].nom,liste_cl[i].soc);
    Elle ne fait rien qu'afficher. Le "broadcast" est fait par la fonction renvoi ->
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      for(i=0;i<nb_client;i++)
        if(liste_cl[i].ip!=liste_cl[nu_client].ip)
          {
    	printf("broadcast vers %s :: %s\n",liste_cl[i].nom,mesg);
    	if(send(liste_cl[i].soc,mesg,strlen(mesg),0)<0)
    	  {
    	    perror(">> Prob sur le write 1");
    	    exit(1);
    	  }
          }
    >La fonction cherche() est une fonction que j'ai créé. Elle me permet de rechercher un client d'après une ip dans ma structure liste_cl.
    >Faire un fork par client me permet d'avoir un processus fils pour discuter avec un client. Pas besoin de faire de select() pour savoir si un client a parlé. C'est utile lors de la connexion de plusieurs client.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Chat basé sur des sockets php5
    Par javhost dans le forum Développement
    Réponses: 1
    Dernier message: 12/07/2005, 16h21
  2. Réponses: 2
    Dernier message: 12/10/2004, 13h04
  3. connection/deconnection des sockets
    Par yotasse dans le forum Développement
    Réponses: 3
    Dernier message: 17/02/2004, 12h08
  4. probleme de gestion de clients avec des sockets....
    Par ludvo dans le forum Réseau
    Réponses: 6
    Dernier message: 25/09/2003, 12h37
  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