Multicast en c sous windows

Résolu
tenrod Messages postés 46 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 11 décembre 2008 - 15 févr. 2008 à 22:45
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 - 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

11 réponses

cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
16 févr. 2008 à 18:38
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.
3
tenrod Messages postés 46 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 11 décembre 2008
17 févr. 2008 à 01:42
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
0
tenrod Messages postés 46 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 11 décembre 2008
18 févr. 2008 à 10:11
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
0
tenrod Messages postés 46 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 11 décembre 2008
21 févr. 2008 à 23:28
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
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
21 févr. 2008 à 23:41
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...
0
tenrod Messages postés 46 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 11 décembre 2008
21 févr. 2008 à 23:46
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
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
22 févr. 2008 à 00:46
mmm...

Tu utilises quel IDE ?
Parce que par exemple dans ce winsock.h, il y est.
0
tenrod Messages postés 46 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 11 décembre 2008
22 févr. 2008 à 10:08
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
0
tenrod Messages postés 46 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 11 décembre 2008
22 févr. 2008 à 10:22
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
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
22 févr. 2008 à 10:22
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.
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
22 févr. 2008 à 10:44
Arf croisement de messages...

Content que tu t'en sois sorti !
0
Rejoignez-nous