Multicast en c sous windows [Résolu]

tenrod 46 Messages postés lundi 22 novembre 2004Date d'inscription 11 décembre 2008 Dernière intervention - 15 févr. 2008 à 22:45 - Dernière réponse : cs_rt15 3982 Messages postés mardi 8 mars 2005Date d'inscription 7 novembre 2014 Dernière intervention
- 22 févr. 2008 à 10:44
Bonsoir a tous,

voila j'ai un petit (voire un gros) pb avec le développement d'une application me permettant de faire du multicast en c sous windows.

J'ai récupéré le code suivant qui logiquement devrait fonctionner :

[code]
/*

multicast.c

- Mark Claypool, 2001

The following program sends or receives multicast packets. If invoked
with one argument, it sends a packet containing the current time to an
arbitrarily chosen multicast group and UDP port. If invoked with no
arguments, it receives and prints these packets. Start it as a sender on
just one host and as a receiver on all the other hosts.

*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include
#include <time.h>
#include <stdio.h>
#include <winsock2.h>

#define EXAMPLE_PORT 16000
#define EXAMPLE_GROUP "239.0.0.1"

main(int argc) {
   struct sockaddr_in addr;
   int addrlen, sock, cnt;
   struct ip_mreq mreq;
   char message[50];

   /* set up socket */
   sock = socket(AF_INET, SOCK_DGRAM, 0);
   if (sock < 0) {
     perror("socket");
     exit(1);
   }
   bzero((char *)&addr, sizeof(addr));
   addr.sin_family = AF_INET;
   addr.sin_addr.s_addr = htonl(INADDR_ANY);
   addr.sin_port = htons(EXAMPLE_PORT);
   addrlen = sizeof(addr);

   if (argc > 1) {
    
      printf("I am a sender.  Sending time...\n");

      /* sender sends time every 3 seconds */
      addr.sin_addr.s_addr = inet_addr(EXAMPLE_GROUP);
      while (1) {
     time_t t = time(0);    /* get current time */
     sprintf(message, "time is %-24.24s", ctime(&t)); /* make readable */
     printf("sending: %s\n", message);
     cnt = sendto(sock, message, sizeof(message), 0,
              (struct sockaddr *) &addr, addrlen);
     if (cnt < 0) {
         perror("sendto");
        exit(1);
     }
     sleep(3);
      }
   } else {

      printf("I am a receiver.  Waiting for messages...\n");

      /* receiver plays out messages */
      if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {       
         perror("bind");
     exit(1);
      }   
      mreq.imr_multiaddr.s_addr = inet_addr(EXAMPLE_GROUP);        
      mreq.imr_interface.s_addr = htonl(INADDR_ANY);        
      if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
             &mreq, sizeof(mreq)) < 0) {
     perror("setsockopt mreq");
     exit(1);
      }        
      while (1) {
      cnt = recvfrom(sock, message, sizeof(message), 0,
            (struct sockaddr *) &addr, &addrlen);
     if (cnt < 0) {
        perror("recvfrom");
        exit(1);
     } else if (cnt == 0) {
         break;
     }
     printf("%s: message = "%s"\n", inet_ntoa(addr.sin_addr), message);
        }
    }
}
[\code]

Mais voila à la compilation c'est le drame :
[code]
c:\documents and settings\administrateur\bureau\toto.c(9) : fatal error C1083: Cannot open include file: 'unistd.h': No such file or directory
c:\documents and settings\administrateur\bureau\toto.c(12) : fatal error C1083: Cannot open include file: 'netinet/in.h': No such file or directory
c:\documents and settings\administrateur\bureau\toto.c(13) : fatal error C1083: Cannot open include file: 'arpa/inet.h': No such file or directory
c:\documents and settings\administrateur\bureau\toto.c(14) : fatal error C1083: Cannot open include file: 'netdb.h': No such file or directory
[\code]
Bref je comprend bien la qu'il s'agit de problèmes de référence à ces différents fichiers mais ma question est la suivante :
quelles librairies dois je utiliser ?
en cherchant sur le net (et oui google ami du développeur) j'ai lu qu'il s'agirait de librairies unix et pas dispo sur windows est ce que ce post que j'ai vu est dans le vrai ?
Si oui quelqu'un a - t - il un bout de code avec les libs nécessaires pour faire communiquer deux postes en multicast ?

Je vous remercie d'avance pour vos réponses.
Vinzouille
Afficher la suite 

Votre réponse

11 réponses

Meilleure réponse
cs_rt15 3982 Messages postés mardi 8 mars 2005Date d'inscription 7 novembre 2014 Dernière intervention - 16 févr. 2008 à 18:38
3
Merci
Salut,

Tu peux virer les trois quarts des includes. stdio, time et winsock devrait suffires.
Plus d'infos sur la compatibilité socket Linux/Windows.
Il faut appeler WSAStartup et WSACleanup.

L'aide de setsockopt de la msdn.

D'aprèscette page de man, l'option IP_ADD_MEMBERSHIP permet de rejoindre un groupe de multicast (Et donne la déclaration de la structure ip_mreq).

L'option IP_ADD_MEMBERSHIP ne semble pas disponible avec winsock2.h, mais elle à l'air ok pour winsock.h.

Le compilo à refusé de casté :
      if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
             &mreq, sizeof(mreq)) < 0) {

=>

      if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
             &(char *)mreq, sizeof(mreq)) < 0) {

Un article sur le multicast sous windows.

Merci cs_rt15 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 95 internautes ce mois-ci

Commenter la réponse de cs_rt15
tenrod 46 Messages postés lundi 22 novembre 2004Date d'inscription 11 décembre 2008 Dernière intervention - 17 févr. 2008 à 01:42
0
Merci
Ok merci


rt15 je vais fouiller du coté des liens que tu m'as filé et je te tiens au courant dès que j'ai du neuf








Vinzouille
Commenter la réponse de tenrod
tenrod 46 Messages postés lundi 22 novembre 2004Date d'inscription 11 décembre 2008 Dernière intervention - 18 févr. 2008 à 10:11
0
Merci
Impec tes exemples m'ont permis de mieux comprendre le systeme des sockets sous windows (jusque la je ne l'avais fait que sous linux...)


Pour ceux qui auraient le meme problème j'ai trouvé ce petit lien qui n'est pas dénué d'intéret



http://www.frameip.com/c-mode-non-connecte/







Vinzouille
Commenter la réponse de tenrod
tenrod 46 Messages postés lundi 22 novembre 2004Date d'inscription 11 décembre 2008 Dernière intervention - 21 févr. 2008 à 23:28
0
Merci
Salut a tous!
J'ai malheureusement un pb supplémentaire avec mes socket en multicast ...
ça se passe a ce niveau

if ((setsockopt(sock_rec, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*) &mc_req, sizeof(mc_req))) < 0)
    {
        printf("setsockopt - IP_ADD_MEMBERSHIP");
        system("PAUSE");
        exit(1);
    }

en fait le "IP_ADD_MEMBERSHIP" ne passe pas, y'a t'il une manipulation spéciale a faire sur ma machine ou y'a il erreur de code?

pour info voici tout le code :

#include <sys/types.h> 
#include <winsock2.h>  
#include <ws2tcpip.h>  
#include <stdio.h>    
#include <stdlib.h>    
#include <string.h>

#define GROUP    "239.137.194.222"
#define PORT    55501
#define MAX_LEN  1024   //taille max réception

int main()
{
    int reuse;
    int sock_rec;                 /* descripteur socket */
    int flag_on = 1;              /* flag socket */
    struct sockaddr_in mc_addr_rec;   /* structure d'adresse de la socket reception */
    char recv_str[MAX_LEN+1];     /* buffer de réception */
    int recv_len;                 /* longueur de la string en réception */
    struct ip_mreq mc_req;        /* structure multicast */
    struct sockaddr_in from_addr; /* source */
    unsigned int from_len;        /* longueur source */
    WSADATA wsaData;              /* structure DLL socket Windows */
    int sock_send;              /* descripteur socket */
    char send_str[MAX_LEN];     /* string à envoyer */
    int send_len;               /* longueur string à envoyer */
    struct sockaddr_in mc_addr_send;   /* structure d'adresse de la socket emission */
    unsigned char ttl=1;     /* time to live */
   
    /* Initialisation de Winsock */
    if (WSAStartup(MAKEWORD(2,0), &wsaData)!=0)
    {
       printf("\nWSAStartup() erreur");
    }
   
    /* création de la socket de réception */
    if ((sock_rec = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
       printf("socket() reception erreur");
    }
   
    /* création de la socket de d'émission */
    if ((sock_send = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
       printf("socket() emission erreur");
    }
   
    /*initialisation de la socket de reception*/
    memset(&mc_addr_rec, 0, sizeof(mc_addr_rec));
    mc_addr_rec.sin_family      = AF_INET;
    mc_addr_rec.sin_addr.s_addr = htonl(INADDR_ANY);
    mc_addr_rec.sin_port        = htons(PORT);
   
    /*initialisation de la socket d'emission*/
    memset(&mc_addr_send, 0, sizeof(mc_addr_send));
    mc_addr_send.sin_family      = AF_INET;
    mc_addr_send.sin_addr.s_addr = htonl(INADDR_ANY);
    mc_addr_send.sin_port        = htons(PORT);
   
    recv_len = sizeof(mc_addr_rec);
    from_len = sizeof(mc_addr_send);
   
    if ((setsockopt(sock_rec, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*) &mc_req, sizeof(mc_req))) < 0)
    {
        printf("setsockopt - IP_ADD_MEMBERSHIP");
        system("PAUSE");
        exit(1);
    }
   
    if (bind(sock_rec, (struct sockaddr *)&mc_addr_rec, sizeof(mc_addr_rec)) < 0)
    {
        printf("bind");
        system("PAUSE");
        exit(1);
    }
   
    /*réception des datagrammes*/
    while (1)
    {
        if (recvfrom(sock_rec, recv_str, sizeof(recv_str), 0, (struct sockaddr *)&mc_addr_rec, &recv_len) < 0)
        {
            printf("recvfrom");
            system("PAUSE");
            exit(1);
        }
        else
        { /* fin de transmission */
            break;
        }
        printf("%s\n", recv_str); /* affichage du message */
    }
   
    /*opération qui permet de fixer la valeur du TTL*/
    if (setsockopt(sock_send, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1)
    {
        printf("setsockopt: IP_MULTICAST_TTL");
    }
   
    /*emission des datagrammes*/
    if (sendto(sock_send, send_str, strlen(send_str), 0, (struct sockaddr *)&mc_addr_send, send_len) < 0)
    {
        printf("sendto");
        system("PAUSE");
        exit(1);
    }
   
    /*quitter le groupe*/
    if (setsockopt(sock_rec, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mc_req, sizeof(mc_req)) == -1)
    {
        printf("setsockopt: IP_DROP_MEMBERSHIP");
    }
   
    /*port réutilisable*/
    reuse = 1;
    if (setsockopt(sock_rec, SOL_SOCKET, SO_REUSEADDR, (int *)&reuse, sizeof(reuse)) == -1) {
        printf("setsockopt: SO_REUSEADDR");
    }
   
    system("PAUSE");   
    return 0;
}

Vinzouille
Commenter la réponse de tenrod
cs_rt15 3982 Messages postés mardi 8 mars 2005Date d'inscription 7 novembre 2014 Dernière intervention - 21 févr. 2008 à 23:41
0
Merci
Des fois, la solution est plus prète qu'on le pense.

Je cite mon message plus haut :

L'option IP_ADD_MEMBERSHIP ne semble pas disponible avec winsock2.h, mais elle à l'air ok pour winsock.h.


Pourtant, tu utilises windock2.h dans ton code...
Commenter la réponse de cs_rt15
tenrod 46 Messages postés lundi 22 novembre 2004Date d'inscription 11 décembre 2008 Dernière intervention - 21 févr. 2008 à 23:46
0
Merci
Salut et merci pour ton aide
bon j'ai remplacé le winsock2.h par winsock.h mais je me retrouve toujours avec le meme pb ...

Vinzouille
Commenter la réponse de tenrod
cs_rt15 3982 Messages postés mardi 8 mars 2005Date d'inscription 7 novembre 2014 Dernière intervention - 22 févr. 2008 à 00:46
0
Merci
mmm...

Tu utilises quel IDE ?
Parce que par exemple dans ce winsock.h, il y est.
Commenter la réponse de cs_rt15
tenrod 46 Messages postés lundi 22 novembre 2004Date d'inscription 11 décembre 2008 Dernière intervention - 22 févr. 2008 à 10:08
0
Merci
Je suis sous dev c++.
Mon OS est windows XP media center
Le pire c'est que j'ai un autre bout de code qui utilise cette méthode et la ça passe ...
Je vais relire encore et encore mon code (même si je doute que ça serve a quelquechose) histoire de voir si j'ai pas zappé une partie vitale ...

Vinzouille
Commenter la réponse de tenrod
tenrod 46 Messages postés lundi 22 novembre 2004Date d'inscription 11 décembre 2008 Dernière intervention - 22 févr. 2008 à 10:22
0
Merci
Bon finalement la relecture a porté ses fruits !
C'est fou ce que ça fait du bien une bonne nuit de sommeil lool
Alors pour ceux que ça intéresse voici le code revu et corrigé :

#include <sys/types.h> 
#include <winsock.h>  
#include <stdio.h>    
#include <stdlib.h>    
#include <string.h>


#define GROUP "239.137.194.222"
#define PORT 55501
#define MAX_LEN  1024   //taille max réception


int main()
{
    int reuse;
    int sock_rec;                 /* descripteur socket */
    int flag_on = 1;              /* flag socket */
    struct sockaddr_in mc_addr_rec;   /* structure d'adresse de la socket reception */
    char recv_str[MAX_LEN+1];     /* buffer de réception */
    int recv_len;                 /* longueur de la string en réception */
    struct ip_mreq mc_req;        /* structure multicast */
    struct sockaddr_in from_addr; /* source */
    unsigned int from_len;        /* longueur source */
    WSADATA wsaData;              /* structure DLL socket Windows */
    int sock_send;              /* descripteur socket */
    char send_str[MAX_LEN];     /* string à envoyer */
    int send_len;               /* longueur string à envoyer */
    struct sockaddr_in mc_addr_send;   /* structure d'adresse de la socket emission */
    unsigned char ttl=1;     /* time to live */
   
    /* Initialisation de Winsock */
    if (WSAStartup(MAKEWORD(2,0), &wsaData)!=0)
    {
       printf("WSAStartup() erreur");
    }
   
    /* création de la socket de réception */
    if ((sock_rec = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
       printf("socket() reception erreur");
    }
   
    /* création de la socket de d'émission */
    if ((sock_send = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
       printf("socket() emission erreur");
    }
   
    if ((setsockopt(sock_rec, SOL_SOCKET, SO_REUSEADDR, (char*)&flag_on,sizeof(flag_on))) < 0)
    {
       printf("setsockopt() erreur - SO_REUSEADDR");
    }
   
    /*initialisation de la socket de reception*/
    memset(&mc_addr_rec, 0, sizeof(mc_addr_rec));
    mc_addr_rec.sin_family      = AF_INET;
    mc_addr_rec.sin_addr.s_addr = htonl(INADDR_ANY);
    mc_addr_rec.sin_port        = htons(PORT);
   
    /*initialisation de la socket d'emission*/
    memset(&mc_addr_send, 0, sizeof(mc_addr_send));
    mc_addr_send.sin_family      = AF_INET;
    mc_addr_send.sin_addr.s_addr = htonl(INADDR_ANY);
    mc_addr_send.sin_port        = htons(PORT);
   
    recv_len = sizeof(mc_addr_rec);
    from_len = sizeof(mc_addr_send);
   
    if (bind(sock_rec, (struct sockaddr *)&mc_addr_rec, sizeof(mc_addr_rec)) < 0)
    {
        printf("bind erreur");
        system("PAUSE");
        exit(1);
    }
   
    mc_req.imr_multiaddr.s_addr = inet_addr(GROUP);
    mc_req.imr_interface.s_addr = htonl(INADDR_ANY);
   
    if (setsockopt(sock_rec, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mc_req, sizeof(mc_req)) < 0)
    {
        printf("setsockopt erreur - IP_ADD_MEMBERSHIP");
        system("PAUSE");
        exit(1);
    }
   
   
   
    /*réception des datagrammes*/
    while (1)
    {
        if (recvfrom(sock_rec, recv_str, sizeof(recv_str), 0, (struct sockaddr *)&mc_addr_rec, &recv_len) < 0)
        {
            printf("recvfrom erreur");
            system("PAUSE");
            exit(1);
        }
        else
        { /* fin de transmission */
            break;
        }
        printf("%s\n", recv_str); /* affichage du message */
    }
   
    /*opération qui permet de fixer la valeur du TTL*/
    if (setsockopt(sock_send, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1)
    {
        printf("setsockopt: IP_MULTICAST_TTL");
    }
   
    /*emission des datagrammes*/
    if (sendto(sock_send, send_str, strlen(send_str), 0, (struct sockaddr *)&mc_addr_send, send_len) < 0)
    {
        printf("sendto");
        system("PAUSE");
        exit(1);
    }
   
    /*quitter le groupe*/
    if (setsockopt(sock_rec, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mc_req, sizeof(mc_req)) == -1)
    {
        printf("setsockopt: IP_DROP_MEMBERSHIP");
    }
   
    /*port réutilisable*/
    reuse = 1;
    if (setsockopt(sock_rec, SOL_SOCKET, SO_REUSEADDR, (int *)&reuse, sizeof(reuse)) == -1) {
        printf("setsockopt: SO_REUSEADDR");
    }
   
    system("PAUSE"); 
    return 0;
}

En tout cas merci pour l'aide ^^





Vinzouille
Commenter la réponse de tenrod
cs_rt15 3982 Messages postés mardi 8 mars 2005Date d'inscription 7 novembre 2014 Dernière intervention - 22 févr. 2008 à 10:22
0
Merci
Tu as peut être une inclusion de winsock2.h qui traine encore quelque part dans ton code.

Si on regarde winsock2, on voit :

#ifndef _WINSOCK2API_
#define _WINSOCK2API_
#define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */

Autrement dit, si on inclut winsock2.h avant winsock.h l'inclusion de winsock.h n'aura aucun effet.
Commenter la réponse de cs_rt15
cs_rt15 3982 Messages postés mardi 8 mars 2005Date d'inscription 7 novembre 2014 Dernière intervention - 22 févr. 2008 à 10:44
0
Merci
Arf croisement de messages...

Content que tu t'en sois sorti !
Commenter la réponse de cs_rt15

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.