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

Linux Discussion :

[RESOLUT]Broadcast UDP sur le réseau


Sujet :

Linux

  1. #1
    Membre averti
    Inscrit en
    Mai 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 15
    Par défaut [RESOLUT]Broadcast UDP sur le réseau
    Bonjour.

    Je suis en train de faire un petit programme dont le but est de localisé (IP) un hote sur le réseau. Ça marche avec un système client-serveur chaque hote voulant être localisé devant faire tourner le serveur.

    Les programmes client (nommé flh) et serveur (flhd) fonctionne très bien en local. Mais dès que j'essaie de localisé un autre hote de mon réseau ça ne fonctionne pas :/ .

    Donc voici les sources:
    flh.c:
    Code c : 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
    /*########################
    # Client FLH (Find Local Host) simple #
    #########################*/
    #include "flh.h"
     
     
    char* option_h = "-h";
    char* help = "Usage: flh [OPTION]\nRecherche un hote sur le réseaux local suivant le protocole FLH.\n\nOption:\n\t-h\tAffiche cette aide.\n\nCode d'erreur:\n\t1\tErreur de création de la socjet.\n\t2\tErreur de nommage de la soccket.\n\t3\tErreur de réception de packet.\n\t4\tErreur de fork.\n\t5\tErreur de récupération du nom d'hote.\n\t6\tErreur d'envoie de message.\n";
     
     
    int main(int argc, char* argv[]){
    	int h = 0;
    	if(argc > 1){
    		if(strcmp(argv[1], option_h) == 0) h = 1;
    	}
    	else{
    		h = 1;
    	}
     
    	if(h){
    		printf("%s", help);
    		exit(0);
    	}
    	else{
    		struct sockaddr_in addr;
    		if(searchHost(argv[1], &addr)){
    			printf("%s\n", inet_ntoa(addr.sin_addr));
    		}
    		else{
    			printf("0.0.0.0\n");
    		}
    	}
    }
    flhd.c:
    Code c : 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
    /*####################
    # Démon FLH (Find Local Host) #
    #####################*/
    #include "flh.h"
     
    char* option_n = "-n";
    char* option_h = "-h";
    char* help = "Usage: flhd [OPTION]\nLance le démon FLH.\nNe passer qu'une option à la fois.\n\nOption:\n\t-h\tAffiche cette aide.\n\t-n\tNe fork pas.\n\nCode d'erreur:\n\t1\tErreur de création de la socjet.\n\t2\tErreur de nommage de la soccket.\n\t3\tErreur de réception de packet.\n\t4\tErreur de fork.\n\t5\tErreur de récupération du nom d'hote.\n\t6\tErreur d'envoie de message.\n";
     
    int main(int argc, char* argv[]){
     
    	int n = 0;
    	if(argc > 1){
    		if(strcmp(argv[1], option_n) == 0) n = 1;
    		else if(strcmp(argv[1], option_h) == 0){
    			printf("%s", help);
    			exit(0);
    		}
    	}
     
    	if(!n){
    		pid_t pid = fork();
    		if(pid == -1){
    			perror("fork()");
    			exit(ERR_FORK);
    		}
    		else if(pid > 0){
    			printf("PID fork: %d\n", pid);
    			exit(0);
    		}
    	}
     
    	char hostname[FLH_MAX_HOSTLEN];
    	if(gethostname(hostname, FLH_MAX_HOSTLEN) == -1){
    		perror("gethostname()");
    		exit(ERR_HOSTNAME);
    	}
     
     
    	int sock;
    	struct sockaddr_in s_addr;//Server infos
     
    	/* ### */
    	if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    		perror("socket()");
    		exit(ERR_SOCK);
    	}
     
    	s_addr.sin_family = AF_INET;
    	s_addr.sin_addr.s_addr = INADDR_ANY;
    	s_addr.sin_port = htons(FLH_SERVER_PORT);
    	memset(&(s_addr.sin_zero), '\0', 8);
     
    	if (bind(sock, (struct sockaddr *)&s_addr,
    		sizeof(struct sockaddr)) == -1) {
    		perror("bind()");
    		exit(ERR_BIND);
    	}
     
    	socklen_t addr_len = sizeof(struct sockaddr);
    	struct sockaddr_in c_addr;//Client infos
    	char* ip = NULL;
    	char buffer[FLH_MAX_MSGLEN];
    	int nob = 0;
    	printf("flhd running on %s...\n", hostname);
    	while(1){
    		if ((nob = recvfrom(sock, buffer, FLH_MAX_MSGLEN-1 , 0, (struct sockaddr *)&c_addr, &addr_len)) == -1) {
    			perror("recvfrom()");
    			exit(ERR_RECV);
    		}
    		else if(strncmp(buffer, WHERE_ARE, WHERE_ARE_LEN) == 0 || nob < FLH_MAX_MSGLEN+2){
    			ip = inet_ntoa(c_addr.sin_addr);
    			char tmp[FLH_MAX_MSGLEN+1];
    			int offset = WHERE_ARE_LEN+1;
    			strncpy(tmp, buffer+offset, nob-offset);
    			tmp[nob-offset] = '\0';
     
    			printf("%s is searching %s", ip, tmp);
     
    			sprintf(tmp, "%s",IM_HERE);
    			if(sendMessage(FLH_CLIENT_PORT, c_addr.sin_addr.s_addr, tmp)) printf(", response sent\n");
    			else printf(", error sendin response\n");
     
    		}
    		else{
    			char tmp[FLH_MAX_MSGLEN+1];
    			strncpy(tmp, buffer, nob);
    			tmp[nob] = '\0';
    			printf("Receive unknow message: %s\n", tmp);
    		}
    	}
    	close(sock);//Pour la forme
     
    	return 0;
    }
    et flh.h:
    Code c : 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
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    /*############################
    # Fonction utile pour FLH (Find Local Host) #
    #############################
    #		Définition du protocole FLH
    #			(Find Local Host)
    #
    #	Le démon écoute en UDP le port 8862
    # (sur l'adresse de broadcast) et attend la
    # réception d'un packet contenant:
    #	"WHERE ARE YOU X"
    # où X est l'hote dont on cherche l'IP.
    # 	Une fois ce message reçut, il répond
    # à l'expéditeur avec le message (UDP):
    # 	"IM HERE"
    # il envoie se message sur le port 8864 que
    # le client doit écouté à ce moment là.
    #
    #	Un client doit donc envoyer le message
    # attendu par le serveur (en broadcast) en y
    # insérant le nom de l'hote qu'il recherche.
    # Puis il écoute en UDP le port 8864 et attend
    # une réponse.
    #
    #	Le serveur ne répond qu'une seul fois.
    # Donc si le client ne reçoit pas de message,
    # il doit refaire une demande.
    ############################*/
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <pthread.h>
     
    //###
    #define ERR_SOCK 1
    #define ERR_BIND 2
    #define ERR_RECV 3
    #define ERR_FORK 4
    #define ERR_HOSTNAME 5
    #define ERR_SENDTO 6
     
     
    #define FLH_SERVER_PORT 8862
    #define FLH_CLIENT_PORT 8864
    #define FLH_MAX_MSGLEN 256
    #define FLH_MAX_HOSTLEN 200
     
     
    const char* WHERE_ARE = "WHERE ARE YOU";
    const int WHERE_ARE_LEN = 13;
     
    const char* IM_HERE = "I AM HERE";
    const int IM_HERE_LEN = 9;
     
    // /!\ Peu bloqué indéfiniment si aucun message reçu /!\
    //Reçoit un message UDP
    char* receiveMessage(int port, int usec, struct sockaddr_in* addr){
    	int sock;
    	struct sockaddr_in s_addr;
    	if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    		perror("socket()");
    		return NULL;
    	}
     
    	s_addr.sin_family = AF_INET;
    	s_addr.sin_addr.s_addr = INADDR_ANY;
    	s_addr.sin_port = htons(port);
    	memset(&(s_addr.sin_zero), '\0', 8);
     
    	if (bind(sock, (struct sockaddr *)&s_addr,
    		sizeof(struct sockaddr)) == -1) {
    		perror("bind()");
    		return NULL;
    	}
     
    	socklen_t addr_len = sizeof(struct sockaddr);
    	struct sockaddr_in c_addr;
     
    	char* ip = NULL;
    	char buffer[FLH_MAX_MSGLEN];
    	int nob = 0;
    	if ((nob = recvfrom(sock, buffer, FLH_MAX_MSGLEN-1 , 0, (struct sockaddr *)&c_addr, &addr_len)) == -1) {
    		perror("recvfrom()");
    		return NULL;
    	}
    	close(sock);
    	*addr = c_addr;
     
    	char* tmp = malloc(nob+sizeof(char));
    	strncpy(tmp, buffer, nob);
    	tmp[nob+1] = '\0';
     
    	return tmp;
    }
     
    //Envoie un message en UDP
    int sendMessage(int port, in_addr_t addr, char* message){
    	int sock;
    	struct sockaddr_in s_addr;
    	if ((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
    		perror("socket()");
    		return 0;
    	}
    	memset((char *) &s_addr, 0, sizeof(s_addr));
    	s_addr.sin_family = AF_INET;
    	s_addr.sin_port = htons(port);
    	s_addr.sin_addr.s_addr = addr;
     
    	int nob = strlen(message);
    	if(nob > FLH_MAX_MSGLEN){
    		return 0;
    	}
    	if (sendto(sock, message, nob, 0, (struct sockaddr *)&s_addr, sizeof(s_addr)) == -1){
    		return 0;
    	}
    	else{
    		return 1;
    	}
    	close(sock);
    }
     
    struct sockaddr_in* G_addr;
    int G_found= 0;
     
    //Thread de recherche
    void* searchThread(void *data){
    	char* tmp = receiveMessage(FLH_CLIENT_PORT, 2000000, G_addr);
     
    	if(tmp != NULL && strcmp(tmp, IM_HERE) == 0){
    		G_found = 1;
    	}
            return NULL;
    }
     
    //Cherhche un hote, 3 tentatives max, 6 secondes max
    int searchHost(char* hostname, struct sockaddr_in* addr){
    	G_addr = addr;
     
    	char buffer[FLH_MAX_MSGLEN];
    	int nob = sprintf(buffer, "%s %s", WHERE_ARE, hostname);
     
    	pthread_t st;
    	pthread_create(&st, NULL, searchThread, NULL);
     
    	sendMessage(FLH_SERVER_PORT, INADDR_ANY, buffer);
    	sleep(1);
    	if(G_found){
    		*addr = *G_addr;
    		return 1;
    	}
     
    	sendMessage(FLH_SERVER_PORT, INADDR_ANY, buffer);
    	sleep(2);
    	if(G_found){
    		*addr = *G_addr;
    		return 1;
    	}
     
    	sendMessage(FLH_SERVER_PORT, INADDR_ANY, buffer);
    	sleep(3);
    	pthread_kill(st, 0);
    	if(G_found){
    		*addr = *G_addr;
    		return 1;
    	}
    	else{
    		return 0;
    	}
    }

    Pour le fonctionnement, tout est expliqué au début du fichier flh.h.

    Le problème est que je n'arrive pas à envoyé les packets sur l'adresse de broadcast.
    Pour envoyé un message j'utilise sendMessage:
    sendMessage(FLH_SERVER_PORT, INADDR_ANY, buffer);
    Mais que je mette INADDR_ANY, INADDR_BROADCAST ou inet_addr("192.168.1.255") je ne voit rien transité sur mon interface réseau (je sniff mon trafic avec Wireshark).
    Si j'utilise une adresse précise cela fonctionne.

    Une idée du problème ?

    J'ai join une archive contenant les sources et un makefile.
    Merci à vous !

    PS:faite pas attention au warning, ça passe !
    Fichiers attachés Fichiers attachés

  2. #2
    Membre averti
    Inscrit en
    Mai 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 15
    Par défaut
    Je progresse.

    Après retouche du code, il s'avère que mes packet ne s'envoie pas sur l'adresse de broadcast (INADDR_ANY ne semble pas correspondre à cela).
    Si je remplace INADDR_ANY pas INADDR_BROADCAST ou inet_addr("192.168.1.255") les packet ne s'envoie pas... (voir searchHost() à la fin de flh.h)

    Une idée ?

  3. #3
    Membre averti
    Inscrit en
    Mai 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 15
    Par défaut
    Résolut:
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int optval = 1;
    setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(int));
    memset((char *) &s_addr, 0, sizeof(s_addr));
    Avec sock la socket utilisé pour envoyer les packets sur l'adresse de broadcast.

Discussions similaires

  1. Réponses: 15
    Dernier message: 21/08/2015, 16h03
  2. Réponses: 4
    Dernier message: 05/08/2011, 11h58
  3. droits en écriture sur le réseau
    Par julien20vt dans le forum MFC
    Réponses: 4
    Dernier message: 25/03/2004, 11h29
  4. Comment obtenir le nom d'un pc sur un réseau?
    Par Depteam1 dans le forum MFC
    Réponses: 2
    Dernier message: 19/02/2004, 10h17
  5. Redimensionnement des Paquets IP sur un Réseau Local
    Par Bonoboo dans le forum Développement
    Réponses: 2
    Dernier message: 12/07/2002, 15h40

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