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 :

Problème avec les sockets


Sujet :

Réseau C

  1. #1
    Futur Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut Problème avec les sockets
    Bonjour à tous,
    J'ai une nouvelle question qui concerne les sockets:
    Je suis en train de programmer un logiciel de discussion instantannée. Le fonctionnement de base est la communication client-serveur.
    J'ai pas mal appris au cours de ce projet sur les sockets mais il me reste une interrogation primordiale. Faut-il ouvrir un socket par client ou faut-il ouvrir un socket par message? Quel est le plus judicieux?
    Je pense que la première solution est plus judicieuse (un socket par client) mais je n'y arrive pas. Pour chaque message qui passe mon serveur ouvre un socket différent!
    Merci à tous ceux qui pourront m'aider!

  2. #2
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par projeticq
    Bonjour à tous,
    J'ai une nouvelle question qui concerne les sockets:
    Je suis en train de programmer un logiciel de discussion instantannée. Le fonctionnement de base est la communication client-serveur.
    J'ai pas mal appris au cours de ce projet sur les sockets mais il me reste une interrogation primordiale. Faut-il ouvrir un socket par client ou faut-il ouvrir un socket par message? Quel est le plus judicieux?
    Je pense que la première solution est plus judicieuse (un socket par client) mais je n'y arrive pas. Pour chaque message qui passe mon serveur ouvre un socket différent!
    Merci à tous ceux qui pourront m'aider!
    Clairement il faut ouvrir un socket par client sinon cela risque de donner un peu n'importe quoi. D'ailleurs je ne vois pas comment tu fais pour ouvrir un socket par client ? Il fait un connect/accept par message ?

    Jc

  3. #3
    Futur Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Oui, je fais un accept par message

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Si tu veux un socket par client, le client lui-même ne doit faire qu'un seul connect(), et garder la connexion ouverte jusqu'à la fin...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Futur Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Ok, mais mon problème c'est que tant que mon serveur fait un accept, il ne peut pas écouter les autres clients puisqu'il est en attente avec accept.

  6. #6
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par projeticq
    Faut-il ouvrir un socket par client ou faut-il ouvrir un socket par message?
    C'est une question d'architecture assez basique... Les réseaux, ça ne s'improvise pas, ça s'apprend... C'est évidemment un socket par client. Mais dans un système de message instantané, le serveur doit servir de relais entre 1 et N clients. (N >=1). Pour une relation point à point : (N=1) :

    CliA <-------->A serv B<--------> CliB

    Sur le serveur, il y a donc 2 sockets clients ouverts (en plus du socket serveur).
    Pas de Wi-Fi à la maison : CPL

  7. #7
    Futur Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Ok, merci. En fait le principe je l'ai bien compris mais je n'arrive pas à le mettre en application.

    Voici une petite partie de mon code. J'ai mis une fonction init_socket(). Celle-ci est éxécutée une seule fois au démarrage de mon serveur. Et j'ai mis une fonction ecoute() qui renvoie une chaine de caractères. Cette fonction doit renvoyer le message du client.
    Mon problème se trouve sur cette fonction je pense. Car cette fonction fait quoi qu'il arrive un accept alors que si le client est déjà connecté j'aimerais qu'il le détecte et ainsi ne pas faire un accept mais juste un recv ou un read. Mais je ne sais pas comment faire!
    Voilà, donc si vous pouvez proposer une petite modif' de ma fonction ecoute() ou d'autres idées, je suis preneur!!!

    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
     
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <sys/wait.h>
     
    #include <netdb.h>
    #include <unistd.h>
    #include <fcntl.h>
     
    #include <grp.h>
    #include <pwd.h>
    #include <errno.h>
    #include <time.h>
     
    #define MAX_CARACT 100
    #define PORT 2007
    #define LISTE_ATTENTE 5
     
    /*Variables globales*/
    int mon_address_longueur, lg=512;
    struct sockaddr_in mon_address, client_address;
    socklen_t longueur;
    int client_socket=-1;
    int ma_socket;
    char *ip_client;
    char *buffer;
    sigset_t ens , ens_old;
    struct sigaction action;
    int ret;
     
    void init_socket()
    {
     
     
    	buffer=malloc(MAX_CARACT+1);
    	printf("INITIALISATION\n");
    	bzero(&mon_address,sizeof(mon_address));
    	mon_address.sin_port = htons(PORT);
    	mon_address.sin_family = AF_INET;
    	mon_address.sin_addr.s_addr = htonl(INADDR_ANY);
     
     
     
    	/* creation de socket */
    	if ((ma_socket = socket(AF_INET,SOCK_STREAM,0))== -1)
    	{
      		printf("Problème avec la creation\n");
      		exit(0);
    	}
     
    	sigfillset(&ens);
    	sigdelset(&ens , SIGINT);
    	sigdelset(&ens , SIGCHLD); 
    	sigprocmask(SIG_SETMASK , &ens , &ens_old ) ;
     
    	action.sa_handler = SIGCHLD_handler;
    	action.sa_mask = ens;
    	action.sa_flags = SA_RESTART;
     
    	if ( sigaction(SIGCHLD , &action , NULL) == -1 )
    	{
    		perror("sigaction");
      		exit(1);
    	}
     
     
    	setbuf(stdout, NULL);
    	setbuf(stdin, NULL);
    	signal(SIGINT, SIGINT_handler);
    	signal(SIGCHLD , SIGCHLD_handler);
     
     
       	ret = bind(ma_socket,(struct sockaddr *)&mon_address, sizeof(mon_address));
       	if (ret!=0)
       	{
         		perror("bind()");
         		exit(1);
       	}
     
    		/* ecoute sur la socket */
    	ret = listen(ma_socket,LISTE_ATTENTE);
       	if (ret!=0)
       	{
          		perror("listen()");
         		exit(1);
       	}
    }
     
    char *ecoute(void)
    {  	
    	mon_address_longueur = sizeof(client_address);
    	longueur = sizeof(client_address);
     
    	client_socket = accept(ma_socket,
                   	         (struct sockaddr *)&client_address,
                   	         &longueur);
     
    	ip_client=inet_ntoa(client_address.sin_addr);
     
     
           	lg = read(client_socket,buffer, MAX_CARACT);
           	write(client_socket,buffer, MAX_CARACT);
     
     	return buffer;
     }

  8. #8
    Futur Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    apparemment il faut utiliser la fonction fork() ou les threads mais je n'arrive pas à les utiliser!!! Please help me! Si quelqu'un a un exemple d'utilisation ou de la documentation sur les threads, toute aide est la bienvenue..

  9. #9
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par projeticq
    apparemment il faut utiliser la fonction fork() ou les threads mais je n'arrive pas à les utiliser!!! Please help me! Si quelqu'un a un exemple d'utilisation ou de la documentation sur les threads, toute aide est la bienvenue..
    Ce n'est pas logique ta facon de faire :

    - Tu fais un accept si un client est là, pas à chaque étape
    - Tant que le client est là, tu géres la connexion en faisant ton boulot de serveur
    - Ensuite, tu fermes la socket.

    Normalement, il faut un thread pour l'accept
    Un tableau/liste chaînée pour la liste de clients présent
    Le thread de base qui parcourt le tableau/liste pour savoir si quelqu'un a besoin de quelque chose.
    Un mutex sur le tableau/liste pour gérer la zone critique.

    Jc

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Pour traiter de multiples clients sans avoir à t'embêter avec du multi-processus (serveur-fork) ou du multithread, tu peux utiliser la fonction select().

    Tu trouveras un exemple ici sur le forum:
    http://www.developpez.net/forums/showthread.php?t=61601

    PS: Ici, le serveur-fork est absolument inapproprié puisque les clients communiquent entre eux. Un serveur-fork, ça ne marche bien que quand il n'y a pas de lien entre les clients (genre serveur HTTP ou ssh)...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Futur Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Merci de vos réponses, je vais voir sur la page et je vais essayer

  12. #12
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par projeticq
    apparemment il faut utiliser la fonction fork() ou les threads mais je n'arrive pas à les utiliser!!! Please help me! Si quelqu'un a un exemple d'utilisation ou de la documentation sur les threads, toute aide est la bienvenue..
    http://emmanuel-delahaye.developpez.com/pthreads.htm
    Pas de Wi-Fi à la maison : CPL

  13. #13
    Futur Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Me revoilà!
    Merci pour toutes vos réponses, elles m'ont permis d'apprendre beaucoup sur les sockets...
    Mais, eh oui, malheureusement il y a un "mais", je n'arrive pas à me dépatouiller ni avec les threads, ni avec fork() et ni avec select(). Cela fait maintenant plusieurs jours que je bosse dessus et IMPOSSIBLE ...
    Alors si quelqu'un a un peu de temps pour se pencher sur mon programme, je vous l'envoi..
    Il y a ci-joint le client et le serveur, ils compilent et s'éxécutent correctement tous les 2. Donc vous pouvez les essayer..
    Pour tester le bon fonctionnement j'ai ouvert un terminal pour le serveur et un terminal pour le client. A l'intérieur du programme, pas de problème car j'ai rentré l'adresse de loopback comme adresse IP pour le serveur (127.0.0.1).
    Ne pas oublier pour la compilation l'option "-lpthread" et pis ça roule! Il y a également un fichier "contacts.txt" dans lequel mon programme client stock des nouveaux contacts. Mais tout ça, vous verrez, ça marche..

    J'explique précisément mon problème:
    1. Le client fait un connect par message envoyé, or pour bien, il faudrait faire un connect une seule fois
    2. Toujours concernant le client, il faut un processus en parallèle qui écoute le serveur pour voir si quelqu'un nous envoi un message(à l'aide des threads je pense)
    3. Pour le serveur => Une attente d'accept pour un nouveau client, tout en recevant des messages
    4. Et enfin, si vous savez, comment pourrais-je "pinger" un client en C (pour vérifier si mes clients sont toujours connectés)


    Je vous ai tous dit, alors, je dis merci d'avance aux plus téméraires...
    Fichiers attachés Fichiers attachés

  14. #14
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par projeticq
    Alors si quelqu'un a un peu de temps pour se pencher sur mon programme, je vous l'envoi..
    Il y a ci-joint le client et le serveur, ils compilent et s'éxécutent correctement tous les 2.
    Tes fichiers ne sont pas clairs. Qu'est-ce qui est du client, qu'est qui est du serveur ? Il devrait y avoir 2 répertoires séparés + un répertoire commun si nécessaire).
    Pas de Wi-Fi à la maison : CPL

  15. #15
    Futur Membre du Club
    Inscrit en
    Janvier 2007
    Messages
    16
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 16
    Points : 6
    Points
    6
    Par défaut
    Ah ok, voilà les fichiers clients et les fichiers serveurs séparés!
    Fichiers attachés Fichiers attachés

Discussions similaires

  1. [OCaml] Petit problème avec les sockets
    Par Fractal LLG dans le forum Caml
    Réponses: 3
    Dernier message: 28/02/2008, 12h18
  2. un serieux problème avec les sockets
    Par dc.sara dans le forum Réseau
    Réponses: 4
    Dernier message: 23/01/2008, 16h11
  3. problèmes avec les sockets
    Par lukbutor dans le forum Réseau
    Réponses: 24
    Dernier message: 23/04/2007, 01h12
  4. Problème avec les sockets et la fonction accept
    Par projeticq dans le forum Réseau
    Réponses: 6
    Dernier message: 13/04/2007, 11h37
  5. [Win32] Problème avec les sockets
    Par mickael777 dans le forum MFC
    Réponses: 3
    Dernier message: 12/08/2005, 11h15

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