begin process at 2008 07 06 15:57:10
1 205 627 membres
195 nouveaux aujourd'hui
14 119 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

Sujet : multicast en c sous windows [ Windows / Réseau & Internet ] (tenrod)

multicast en c sous windows le 15/02/2008 22:45:15

tenrod
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 <arpa/inet.h>
#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


Re : multicast en c sous windows le 16/02/2008 18:38:33

rt15
Membre Club
Réponse acceptée !
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ès cette 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.


Re : multicast en c sous windows le 17/02/2008 01:42:15

tenrod
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


Re : multicast en c sous windows le 18/02/2008 10:11:00

tenrod

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

[ Lien ]

Vinzouille


Re : multicast en c sous windows le 21/02/2008 23:28:11

tenrod
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


Re : multicast en c sous windows le 21/02/2008 23:41:42

rt15
Membre Club
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...


Re : multicast en c sous windows le 21/02/2008 23:46:33

tenrod
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


Re : multicast en c sous windows le 22/02/2008 00:46:00

rt15
Membre Club
mmm...

Tu utilises quel IDE ?
Parce que par exemple dans ce winsock.h, il y est.



Re : multicast en c sous windows le 22/02/2008 10:08:02

tenrod
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


Re : multicast en c sous windows le 22/02/2008 10:22:00

tenrod

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



[Page 1 Page 2]
Classé sous : message, include, sock, addr, if

Participer à cet échange

Pub



Appels d'offres

Plugin Dialer outlook
Budget : 2 000€
Travail graphique- ill...
Budget : 1 000€
creation de marque et ...
Budget : 1 000€

CalendriCode

Juillet 2008
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Téléchargements

Boutique

Boutique de goodies CodeS-SourceS