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 :

Petite question sur les sockets


Sujet :

Réseau C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 96
    Points : 44
    Points
    44
    Par défaut Petite question sur les sockets
    Bonjour,

    J'ai débuté avec les Sockets la semaine dernière et plusieurs questions me viennent à l'esprit pour le moment. C'est donc tout naturellement que je vous les pose :

    - L'utilisation des Sockets avec TCP requiert t-il, à chaque échange entre le client et le serveur, un nouvel appel de connexion ?
    - Si, pour des besoins spécifiques, le client doit également envoyer des messages au serveur - notamment lorsque celui-ci se déconnecte -, est-il possible de développer cette fonctionnalité en incluant une condition sur la réception dans ma boucle d'écoute côté serveur ?

    Pour l'instant j'ai développé une application assez basique :
    - Une application "Client"
    - Une application "Serveur"

    - Sur mon application Client j'ai un contrôle EDIT dans lequel l'utilisateur saisit l'adresse IP sur serveur auquel il souhaite se connecter.
    - Si la connexion passe, le serveur lui envoie un message.

    Jusqu'ici tout va bien. Maintenant, j'aimerais simplement faire en sorte que, lorsque l'utilisateur clique sur un contrôle BUTTON de déconnexion, l'application cliente envoie un message de déconnexion.
    Pour le moment, j'essaye d'afficher ce message sur la partie serveur, sans succès.

    Je m'y prends sans doute mal, alors si toutefois vous aviez un peu de temps, un peu d'aide serait la bienvenue.

    Voici mon code client (associé au bouton de contrôle de connexion) :

    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
    void CClientView::OnBnClickedButtonConnexion()
    {
    	UpdateData(TRUE);
     
    	std::string s = CT2A(m_strServeur.GetBuffer(m_strServeur.GetLength()+1));
    	ip = s.c_str();
    	//m_strServeur.ReleaseBuffer();
    
    	SOCKADDR_IN sin;
    	sock = socket(AF_INET, SOCK_STREAM, 0);
    	sin.sin_addr.s_addr = inet_addr(ip);
    	sin.sin_family = AF_INET;
    	sin.sin_port = htons(1500);
    	connect(sock, (SOCKADDR *)&sin, sizeof(sin));
    	
    	char buffer[255];
    	recv(sock, buffer, sizeof(buffer), 0);
    
    	if(recvMessage = "ok")
    	{
    		m_ButtonConnexion.EnableWindow(FALSE);
    		m_ButtonDeconnexion.EnableWindow(TRUE);
    		m_strNote = "La connexion est établie...";
    		UpdateData(FALSE);
    	}
    	//closesocket(sock);
    	//WSACleanup();
    }
    Les vérifications ne sont pas encore effectuées, je pars pour l'instant du principe que tout se passe correctement.

    Voici mon code client (associé au bouton de contrôle déconnexion)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void CClientView::OnBnClickedButtonDeconnexion()
    {
    	send(sock, "pok", sizeof("pok"),0);
    }
    Enfin, voici mon code côté serveur (associé à un contrôle réception)

    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
     
    void CServeurView::OnBnClickedButtonEcoute()
    {
    	WSADATA WSAData;
    	WSAStartup(MAKEWORD(2,0), &WSAData);
     
    	char buffer[255];
    	SOCKET socketEcoute;
    	SOCKET socketRelais;
    	SOCKADDR_IN sinEcoute;
    	SOCKADDR_IN sinRelais;
    	socketEcoute = socket(AF_INET, SOCK_STREAM, 0);
    	sinEcoute.sin_addr.s_addr = INADDR_ANY;
    	sinEcoute.sin_family = AF_INET;
    	sinEcoute.sin_port = htons(1500);
    	bind(socketEcoute, (SOCKADDR *)&sinEcoute, sizeof(sinEcoute));
    	listen(socketEcoute, 0);
    	while(1)
    	{
    		int sinsize = sizeof(sinRelais);
    		if((socketRelais = 
                       accept(socketEcoute, (SOCKADDR *)&sinRelais, &sinsize)) !=
                                                                                INVALID_SOCKET)
    		{	
    			send(socketRelais, "ok", sizeof("ok"),0);
    		}
    		if(recv(socketEcoute, buffer, sizeof(buffer), 0) != 
                                                                                  SOCKET_ERROR)
    		{
    			FILE * pFile; 
    			pFile = fopen("toto.txt", "a");
    			fprintf(pFile,"RECV   = %s\n",buffer);
    			fclose(pFile);
    		}
    	}
    }
    (recv() me renvoie une erreur).

    A terme je pense que les deux applications seront à la fois serveur, donc j'ai besoin de comprendre la subtilité du schème.

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par theawe Voir le message
    L'utilisation des Sockets avec TCP requiert t-il, à chaque échange entre le client et le serveur, un nouvel appel de connexion ?
    NON, la connexion reste établie jusqu'u ce qu'elle soit fermée par une des 2 extrémités.

    Citation Envoyé par theawe Voir le message
    - Si, pour des besoins spécifiques, le client doit également envoyer des messages au serveur - notamment lorsque celui-ci se déconnecte -, est-il possible de développer cette fonctionnalité en incluant une condition sur la réception dans ma boucle d'écoute côté serveur ?
    Dans ce que tu dis, il y a 2 choses différentes et je ne pense pas que tu les aient encore saisies.
    Il y a la fermeture applicative et la fermeture socket.
    • La fermeture applicative, c'est quand une des 2 extrémités prévient l'autre en lui disant "Je vais fermer, tu peux faire le ménage". C'est l'équivalent du "BYE" pour le protocole FTP ou du "QUIT" pour le protocole SMTP
    • La fermeture socket, c'est la commande closesocket() qui permet de demander au système de fermer le socket.

    Dans ce que tu dis, on peut imaginer le scenario suivant :
    • Le client envoi la commande "FIN de travail" au serveur avec send()
    • Le serveur reçoit cette commande avec recv()
    • Le serveur acquitte cette commande avec le résultat "OK, je vais le faire". Cette étape n'est pas forcemment onbligatoire
    • Le serveur nettoie l'environnement (si nécessaire)
    • Le serveur ferme le socket avec closesocket()
    • Le client reçoit la notification de fermeture du socket
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 96
    Points : 44
    Points
    44
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Dans ce que tu dis, on peut imaginer le scenario suivant :
    • Le client envoi la commande "FIN de travail" au serveur avec send()
    • Le serveur reçoit cette commande avec recv()
    • Le serveur acquitte cette commande avec le résultat "OK, je vais le faire". Cette étape n'est pas forcemment onbligatoire
    • Le serveur nettoie l'environnement (si nécessaire)
    • Le serveur ferme le socket avec closesocket()
    • Le client reçoit la notification de fermeture du socket
    Après réception d'un message par le client par le biais du socket n, peut-on réutiliser ce même socket pour l'envoi d'un message au serveur ?

    Je bloque au premier point du scénario, je ne parviens pas à recevoir le message envoyé depuis le client sur le serveur. J'ai testé le résultat de l'envoi et il me retourne le nombre d'octets envoyé. Le problème vient donc de la réception serveur.

  4. #4
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par theawe Voir le message
    Après réception d'un message par le client par le biais du socket n, peut-on réutiliser ce même socket pour l'envoi d'un message au serveur ?
    OUI, c'est comme cela que cela doit marcher
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    En regardant ton code, je viens de voir où tu fais l'erreur dans le code de ton serveur

    Tu as 1 socket serveur socketEcoute
    • tu fais un accept sur ce socket socketRelais = accept(socketEcoute, ...)
    • Tous tes échanges entre le client et ton nouveau socket doivent se faire avec socketRelais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if(recv(socketRelais, ... != SOCKET_ERROR)
    if(send(socketRelais, ... != SOCKET_ERROR)
    Mais ton code va te poser un problème dès lors que tu voudras que 2 clients simultanément se connectent à ton serveur. Pour l'instant l'architecture de ce code est bonne si tu ne veux gérer qu'un seul client à la fois.

    Pour gérer plusieurs clients simultanément, il faudra passer par un select() pour écouter tous les sockets en une seule fois ou alors par du multi thread (un thread pour le socket serveur et un nouveau thread pour chacun des nouveaux clients qui gère le socketRelais spécifique à ce client). Regarde un peu ce tuto Les socket en C
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 96
    Points : 44
    Points
    44
    Par défaut
    (J'avais un doute quant à la place du topic, désolé d'avoir vu faux)

    Merci pour le tutoriel, je ne l'avais pas trouvé en cherchant sur google (dommage d'ailleurs). Je vais bosser un peu tout ça, développer étape par étape, tout en laissant ce fil de discussion non résolu pour le moment.

    Merci d'avoir relevé l'erreur de mon code, ça fonctionne .

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 96
    Points : 44
    Points
    44
    Par défaut
    Bonjour,

    Lorsqu'un message est envoyé depuis le client et correctement reçu depuis le serveur, peut on à nouveau recevoir des messages depuis le serveur ?

    Dans mon application client, j'envoie des messages qui varient en fonction d'une demande d'action spécifique. Du côté serveur (dans la boucle while(1)), je vérifie si un message est effectivement reçu et si oui, en fonction de son contenu je fais tel ou tel traitement. Seulement voilà, je ne parviens pas à retourner en arrière de sorte que le serveur se remette en attente de réception une fois le traitement effectué.

    (Je travaille pour le moment avec un seul client.)

    Un exemple du problème qui se présente à moi :

    Je me connecte au serveur, le serveur m'envoie un message me spécifiant que je suis effectivement connecté.
    Deux choix se présentent alors au client :

    • La déconnexion : envoie d'un message spécifique de déconnexion.
    • L'affichage de la liste des fichiers disponibles à importer sur le client depuis le serveur.


    Rien n'est associé pour le moment au message de déconnexion. Le traitement de l'affichage des fichiers, lui, fonctionne. Une fois que le ce dernier a été effectué, j'aimerais revenir au point de départ, c'est-à-dire en mode "attente" de réception. Le problème qui se pose c'est qu'une fois que j'ai reçu un message depuis le serveur, la fonction recv n'est plus lue par le programme. J'ai tenté de sortir de mon traitement avec le break mais cela n'a pas été concluant. Y a t-il une méthode particulière à respecter ?

Discussions similaires

  1. Encore une petite question sur les sockets...
    Par damien99 dans le forum MFC
    Réponses: 4
    Dernier message: 15/02/2006, 14h22
  2. Petites question sur les onglets...
    Par jarod_bx dans le forum Access
    Réponses: 1
    Dernier message: 20/12/2005, 18h45
  3. [ATL] Petite question sur les progress bar
    Par MrMaze dans le forum MFC
    Réponses: 1
    Dernier message: 06/05/2005, 09h40
  4. Réponses: 3
    Dernier message: 08/12/2004, 13h58
  5. Petite question sur les performances de Postgres ...
    Par cb44 dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 13/01/2004, 13h49

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