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

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mai 2017
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : mai 2017
    Messages : 5
    Points : 2
    Points
    2

    Par défaut Sockets et messagerie instantanée

    Bonjour, je me suis récemment lancé dans la programmation TCP et j'essaie de construire une petite messagerie instantanée.Un serveur, des clients liés 2 par 2. Mais jusque là avec ce code je n'arrive qu'à communiquer entre serveur et clients. Je coince au niveau de la communication client client. Comment envoyer le buffer d'une socket liant le client et le serveur à une autre socket liant le serveur et un autre client ?
    Code C 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
    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
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    // en-tetes C standards
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    // en-tete unix:
    #include <unistd.h>
    // en-tetes reseaux:
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #define BUFFER_SIZE 1024
    // déclaration de variables
    int clients=0;
    int tabClients[][]=0;
    int cree_socket_tcp_ip();
    int affiche_adresse_socket(int sock);
    int affiche_adresse_distante(int sock);
    int connexion(int socket_contact);
    void traitement( int socket );
    int main() {
    	printf("Bonjour!\n");
    	int socket_contact;
    	int socket_connectee;
    	pid_t pid;
    	// creation socket de contact:
    	socket_contact = cree_socket_tcp_ip();
    	// affichage adresse locale:
    	affiche_adresse_socket( socket_contact );
    	//  ecoute sur le port. Jusqu'à 6 requêtes possibles:
    	listen( socket_contact, 6 );
    	while (1) {
    		socket_connectee = connexion( socket_contact );
    		pid = fork();
    		if (pid==-1) {
    			perror( "fork" );
    			close( socket_contact );
    			close( socket_connectee );
    			exit(1);
    		}
    		else if (pid==0) {
    			// fils -> on continue avec la socket connectée:
    			close(socket_contact);
    			// affichage machine distante:
    			affiche_adresse_distante( socket_connectee );
    			// communication:
    			traitement( socket_connectee );
    			close(socket_connectee);
    			exit(0);
    		}
    		else {
    			// père -> traiter la requ`ete suivante:
    			close(socket_connectee);
    		}
    	}
    	close(socket_contact);
    	printf("Au revoir!\n");
    }
    int connexion(int socket_contact) {
    	struct sockaddr_in adresse;
    	int socket_connectee;
    	socklen_t longueur;
    	socket_connectee = accept(socket_contact,(struct sockaddr*)&adresse,&longueur);
    		if (socket_connectee < 0){
    			perror( "accept" );
    			close(socket_contact);
    			exit(11);
    		}
    		else{
    			printf("Creation socket client \n");
    			clients+=1;
    			printf("Nombre de clients: %d\n", clients);
    			/*if (clients%2 ==0){
    				cree_socket_tcp_ip();
    			}*/
                close(socket_contact);
    	}
    return socket_connectee;
    }
    void traitement( int socket_connectee ) {
    	char buffer[BUFFER_SIZE];
    	int nb;
    	// envoi du message d'accueil:
    	strcpy( buffer, "Bienvenue sur le serveur. Ecrivez quelque chose...(exit pour sortir) " );
    	write( socket_connectee, buffer, strlen(buffer)+1 );
    	// reception des reponses de la machine distante:
    	while (1) {
    		nb = read(socket_connectee, buffer, BUFFER_SIZE);
    		// rupture de la connexion par le client:
    		if ( nb == 0)
    			break;
    			buffer[nb-1] = '\0';
    			// affichage:
    			printf( "Client: %s\n", buffer );
    			// sortie demandée
    			if ( !strcmp( buffer, "exit" ) )
    				break;
    	}
    }
    int cree_socket_tcp_ip(){
    	int sock;
    	struct sockaddr_in adresse;
    	// IP et TCP:
    	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    		fprintf(stderr, "Erreur socket.\n");
    		exit(1);
    	}
    	memset(&adresse, 0, sizeof(struct sockaddr_in));
    	adresse.sin_family = AF_INET;  // Protocol IP
    	adresse.sin_port = htons(33016);  // port 33016
    	inet_aton("127.0.0.1", &adresse.sin_addr); // IP localhost
    	if (bind(sock, (struct sockaddr*) &adresse, sizeof(struct sockaddr_in)) < 0){
    		close(sock);
    		perror("Erreur bind");
    		exit(2);
    	}
    return sock;
    }
    int affiche_adresse_socket(int sock){
    	struct sockaddr_in adresse;
    	socklen_t longueur;
    	longueur = sizeof(struct sockaddr_in);
    	if (getsockname(sock, (struct sockaddr*)&adresse, &longueur) < 0){
    		close(sock);
    		perror("Erreur getsockname");
    		exit(3);
    	}
    	printf("IP = %s, Port = %u\n", inet_ntoa(adresse.sin_addr), ntohs(adresse.sin_port));
    return 0;
    }
    int affiche_adresse_distante(int sock){
    	struct sockaddr_in adresse;
    	socklen_t longueur;
    	char buffer[BUFFER_SIZE];
    	longueur = sizeof(struct sockaddr_in);
    	if (getpeername(sock, (struct sockaddr*) &adresse, &longueur) < 0) {
    		perror( "getpeername" );
    		close(sock);
    		exit(12);
    	}
    	printf( "Client d'adresse IP = %s, sur le port = %u\n", inet_ntoa(adresse.sin_addr), ntohs(adresse.sin_port) );
    return 0;
     
    }
    Je pensais créer un tableau de clients, enregistrer leurs informations et trouver un moyen de couper la connexion par multiple de 2 utilisateurs.

    Code C du client :
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #define BUFFER_SIZE 1024
     
    int cree_socket_tcp_ip_client();
    int affiche_adresse_socket(int sock);
    void communication( int socket );
    int main(int argc, char *argv[] ) {
    	printf("Bonjour!\n");
    	int port;
    	int socket;
    	if ( argc!= 3 ) {
    		printf("usage: connect num_IP num_port.\n");
    		exit(1);
    	}
    	else
    		// conversion chaine de caractere -> nombre entier:
    		sscanf( argv[2], "%d", &port );
    		// création socket de connexion:
    		socket = cree_socket_tcp_ip_client( argv[1], port );
    		affiche_adresse_socket( socket );
    		communication( socket );
    		close( socket );
    		printf("Au revoir!\n");
    	}
    	void communication( int socket ) {
    		char buffer[BUFFER_SIZE];
    		int nb;
    		// réception du message d'accueil:
    		nb= read(socket, buffer, BUFFER_SIZE);
    		buffer[nb-2] = '\0';
    		// affichage:
    		printf( "%s\n", buffer );
    		// envoi des r ?eponses:
    		while(1) {
    			fgets( buffer, BUFFER_SIZE, stdin );
    			write( socket, buffer, strlen(buffer) );
    			if ( !strcmp( buffer, "exit" ) )
    				break;
    		}
    	}
    	int cree_socket_tcp_ip_client( char *ip, int port )
    	{
    	int socket_contact;
    	struct sockaddr_in adresse;
    	// IP et TCP:
    	if ((socket_contact = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    		perror("Erreur socket");
    		exit(1);
    	}
    	// initialisation `a 0 puis affectation des champs:
    	memset(&adresse, 0, sizeof(struct sockaddr_in));
    	adresse.sin_family = AF_INET;  // Protocol IP
    	adresse.sin_port = htons(port);  // port 33016
    	inet_aton(ip, &adresse.sin_addr); // IP internet
    	// connexion au site local:
    	if (connect(socket_contact, (struct sockaddr*) &adresse, sizeof(struct sockaddr_in)) < 0){
    		close(socket_contact);
    		perror("Erreur connect");
    		exit(2);
    	}
    	return socket_contact;
    	}
    int affiche_adresse_socket(int sock)
    {
    	struct sockaddr_in adresse;
    	socklen_t longueur;
    	longueur = sizeof(struct sockaddr_in);
    	if (getsockname(sock, (struct sockaddr*)&adresse, &longueur) < 0){
    		close(sock);
    		perror("Erreur getsockname");
    		exit(3);
    	}
    	printf("IP = %s, Port = %u\n", inet_ntoa(adresse.sin_addr), ntohs(adresse.sin_port));
    return 0;
    }
    J'ai voulu aussi créer une socket liant directement les clients mais je me suis dit que ça ne servait plus à rien d'avoir un serveur, à moins que je puisse créer cette socket depuis le programme serveur (chose que je ne sais pas faire).

  2. #2
    Rédacteur/Modérateur

    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    5 595
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 5 595
    Points : 24 554
    Points
    24 554

    Par défaut

    Salut,

    si tu a une topologie client-serveur, les clients sont connectés au serveur mais pas entre eux. Chaque client connait le serveur uniquement, et seul le serveur connait tous les clients.
    Donc pour envoyer un message à un autre client, il faut l'envoyer au serveur qui le redirigera vers le client ciblé.

    Si tu veux faire du client-client, il faut sinon faire du P2P, et donc de l'UDP. Je te déconseille cette voie qui est bien plus complexe.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mai 2017
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : mai 2017
    Messages : 5
    Points : 2
    Points
    2

    Par défaut

    Merci pour ta réponse. Du coup je voulais savoir comment je pourrais retirer le contenu de la socket A pour le mettre dans la socket B sachant que je ne veux faire qu'un code client. J'ai essayé de faire un write (client) - read (server) - write (client), mais là ça coince. Est ce possible de comparer le port et/ou l'ip des deux clients pour ensuite mettre une condition dans le code serveur qui dit que si les propriétés diffèrent, envoyer le message au client différent de l'envoyeur ?
    Je dis ça comme ça parce que je ne suis pas encore assez familier avec le C

  4. #4
    Rédacteur/Modérateur

    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    5 595
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 5 595
    Points : 24 554
    Points
    24 554

    Par défaut

    Sur le serveur tu as une liste de clients qui sont chacun définis par un identifiant unique qui est le socket récupéré via accept à leur connexion.
    A:send -> Serveur:recv -> Serveur:send to B -> B:recv

    Pour plus d'informations tu peux lire la série de cours depuis ma signature.
    En particulier le dernier est un serveur de chat simple justement. C'est un exercice sympa à faire pour apprendre TCP.
    C'est en C++ mais reste applicable en C.
    https://bousk.developpez.com/cours/r...-mini-serveur/
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mai 2017
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : mai 2017
    Messages : 5
    Points : 2
    Points
    2

    Par défaut

    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
    nb= read(socket, buffer, BUFFER_SIZE);
    		buffer[nb-2] = '\0';
    		// affichage:
    		printf( "%s\n", buffer );
    		// envoi des r ?eponses:
    		while(1) {
    			fgets( buffer, BUFFER_SIZE, stdin );
    			write( socket, buffer, strlen(buffer) );
                nb2= read(socket, buffer, BUFFER_SIZE);
                buffer[nb2-2]='\0';
                printf("Client distant: %s\n",buffer);
    			if ( !strcmp( buffer, "exit" ) )
    				break;
    		}
    	}
    J'ai rajouté ceci dans mon code pensant que j'allais avoir un resultat mas il ne fait que retourner le message au client d'origine.

Discussions similaires

  1. messagerie instantanée et sockets
    Par Spidy dans le forum IO
    Réponses: 1
    Dernier message: 13/05/2010, 22h34
  2. Messagerie instantanée en socket java
    Par nzo70 dans le forum IO
    Réponses: 23
    Dernier message: 08/12/2008, 10h57
  3. Messagerie instantanée amsn
    Par rach20032 dans le forum RedHat / CentOS / Fedora
    Réponses: 3
    Dernier message: 27/07/2007, 13h25
  4. identification en messagerie instantanée
    Par young077 dans le forum Développement
    Réponses: 2
    Dernier message: 15/01/2007, 12h53
  5. Aide pour logiciel de messagerie instantanée
    Par tibou8985 dans le forum Tomcat et TomEE
    Réponses: 3
    Dernier message: 09/01/2007, 13h36

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