2009-07-24 15 views
3

Ok, si vous jetez un coup d'œil à mes questions précédentes, je travaille à l'établissement d'une connexion simple avec des sockets C (je suis encore relativement nouveau tout l'aspect réseau d'un programme, mais tout le monde doit commencer quelque part, non?). J'ai inclus le code ci-dessous que j'ai jusqu'ici et quand je l'exécute, je n'obtiens pas d'erreurs, mais en même temps, je ne reçois pas le paquet à l'autre extrémité. En passant, je programme des sockets multicast en objectif-C et "msgStatus" est juste une étiquette dans mon interface graphique (elle est connectée correctement, donc il n'y a pas de problème ici). Je ne vois pas où je vais mal. Quelqu'un pourrait-il m'aider ou me diriger dans la bonne direction? Merci!Aide pour l'envoi/la réception de paquets UDP - C Sockets

#define MAX_LEN 1024 /* maximum string size to send */ 
#define MIN_PORT 1024 /* minimum port allowed */ 
#define MAX_PORT 65535 /* maximum port allowed */ 
#define MYPORT 5673  /* port we will be using for our multicast socket */ 

    -(void)broadcastMessage {//(NSString*)msg { 
     NSLog(@"broadcastMessage - Stage 1"); 
     NSString *msg = @"From Master"; 
     mc_ttl = 3; // number of node hops the message is allowed to travel across the network 

     // define the port we will be using 
     mc_port = MYPORT; 

     /* create a socket for sending to the multicast address */ 
    if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 
     NSLog(@"ERROR: broadcastMessage - socket() failed"); 
     return; 
    } 

    mc_addr.sin_family  = AF_INET; 
    mc_addr.sin_addr.s_addr = inet_addr("225.0.0.37"); 
    mc_addr.sin_port  = htons(mc_port); 

    if (bind(sock, (struct sockaddr *) &mc_addr, sizeof(struct sockaddr_in)) < 0) { 
     NSLog(@"ERROR: bind not successful"); 
     return; 
    } 

    NSLog(@"broadcastMessage - Stage 2"); 
    /* set the TTL (time to live/hop count) for the send */ 
    if ((setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (void*) &mc_ttl, sizeof(mc_ttl))) < 0) { 
     NSLog(@"ERROR: broadcastMessage - setsockopt() failed"); 
     return; 
    } 

    NSLog(@"broadcastMessage - Stage 3"); 
    /* construct a multicast address structure - erase everything in the structure first*/ 
    memset(&mc_addr, 0, sizeof(mc_addr)); 

    // prepare the message to be sent 
    char send_str[MAX_LEN]; 

    /* clear send buffer */ 
    memset(send_str, 0, sizeof(send_str)); 

    // convert the message to a C string to send 
    [msg getCString:send_str maxLength:MAX_LEN encoding:NSASCIIStringEncoding]; 

    //while (fgets(send_str, MAX_LEN, stdin)) { 
     NSLog(@"broadcastMessage - Stage 4"); 
    // send_len = strlen(send_str); 

    /* send string to multicast address */ 
    if ((sendto(sock, send_str, sizeof(send_str), 0, (struct sockaddr *) &mc_addr, sizeof(mc_addr))) != sizeof(send_str)) { 
     NSLog(@"ERROR: broadcastMessage - sendto() sent incorrect number of bytes"); 
     return; 
    } 

    NSLog(@"broadcastMessage - Stage 5"); 


    /* clear send buffer */ 
    memset(send_str, 0, sizeof(send_str)); 

    NSLog(@"broadcastMessage - Stage 6"); 
    close(sock); 
} 


-(void)listenForPackets { 
    listeningFlag_on = 1; 

    NSLog(@"listenForPackets - Stage 1"); 
    if ((listeningSock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 
     NSLog(@"ERROR: listenForPackets - socket() failed"); 
     return;       // make the method return an int instead of void and use this statement to check for errors 
    } 

    // set reuse port to on to allow multiple binds per host 
    if ((setsockopt(listeningSock, SOL_SOCKET, SO_REUSEADDR, &listeningFlag_on, sizeof(listeningFlag_on))) < 0) { 
     NSLog(@"ERROR: listenForPackets - setsockopt() failed"); 
     return;       // make the method return an int instead of void and use this statement to check for errors 
    } 

    NSLog(@"listenForPackets - Stage 2"); 
    // construct a multicast address structure after erasing anything in the listeningmc_addr structure 
    memset(&listeningmc_addr, 0, sizeof(listeningmc_addr)); 
    listeningmc_addr.sin_family  = AF_INET; 
    listeningmc_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    listeningmc_addr.sin_port  = htons(mc_port); 

    // bind multicast address to socket 
    if ((bind(listeningSock, (struct sockaddr *) &listeningmc_addr, sizeof(listeningmc_addr))) < 0) { 
     NSLog(@"ERROR: listenForPackets - bind() failed"); 
     return;       // make the method return an int instead of void and use this statement to check for errors 
    } 

    //****************************************************************************************************************************** 
    //****************************************************************************************************************************** 
    NSString *ipAddress = [[NSString alloc] initWithString:self.getIPAddress]; 
    const char *tmp = [ipAddress UTF8String]; 
    listeningMc_addr_str = tmp; 

    printf("%s\n", listeningMc_addr_str); 

    listeningMc_req.imr_multiaddr.s_addr = inet_addr("225.0.0.37"); 
    listeningMc_req.imr_interface.s_addr = htonl(INADDR_ANY); 


    // send an ADD MEMBERSHIP message via setsockopt 
    if ((setsockopt(listeningSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*) &listeningMc_req, sizeof(listeningMc_req))) < 0) { 
     NSLog(@"ERROR: listenForPackets - setsockopt() failed"); 
     int err = errno; 
     NSLog(@"errno - %i", err); 
     NSLog(@"Error = %s", strerror(err)); 
     perror("ERROR"); 
     return;       // make the method return an int instead of void and use this statement to check for errors 
    } 

    NSLog(@"listenForPackets - Stage 3"); 
    for (;;) {   // loop forever 

     // clear the receive buffers & structs 
     memset(listeningRecv_str, 0, sizeof(listeningRecv_str)); 
     listeningFrom_len = sizeof(listeningFrom_addr); 
     memset(&listeningFrom_addr, 0, listeningFrom_len); 

     // block waiting to receive a packet 
     if ((listeningRecv_len = recvfrom(listeningSock, listeningRecv_str, MAX_LEN, 0, (struct sockaddr*)&listeningFrom_addr, &listeningFrom_len)) < 0) { 
      NSLog(@"ERROR: listenForPackets - recvfrom() failed"); 
      return;      // make the method return an int instead of void and use this statement to check for errors 
     } 
     NSLog(@"listenForPackets - Stage 4"); 

     NSString *tmpy = [[NSString alloc] initWithCString:listeningRecv_str encoding:NSASCIIStringEncoding]; 
      msgStatus.text = tmpy; 
      NSLog(@"ERROR"); 
     } 
     // received string 
     printf("Received %d bytes from %s: ", listeningRecv_len, inet_ntoa(listeningFrom_addr.sin_addr)); 
     printf("%s", listeningRecv_str); 
    } 

    // send a DROP MEMBERSHIP message via setsockopt 
    if ((setsockopt(listeningSock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void*) &listeningMc_req, sizeof(listeningMc_req))) < 0) { 
     NSLog(@"ERROR: listenForPackets - setsockopt() failed"); 
     //return 1;       // make the method return an int instead of void and use this statement to check for errors 
    } 

    close(listeningSock); 
    NSLog(@"listenForPackets - Stage 5 - Complete");  
} 

Voici le code que j'utilise pour extraire mon adresse IP.

-(NSString *)getIPAddress { 
    NSString *address = @"error"; 
    struct ifaddrs *interfaces; // = NULL; 
    struct ifaddrs *temp_addr; // = NULL; 
    int success = 0; 

    // retrieve the current interfaces - returns 0 on success 
    success = getifaddrs(&interfaces); 
    if (success == 0) 
    { 
     // Loop through linked list of interfaces 
     temp_addr = interfaces; 
     while(temp_addr != NULL) 
     { 
      if(temp_addr->ifa_addr->sa_family == AF_INET) 
      { 
       // Check if interface is en0 which is the wifi connection on the iPhone 
       if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) 
       { 
        // Get NSString from C String 
        address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)]; 
       } 
      } 
      temp_addr = temp_addr->ifa_next; 
     } 
    } 

    // Free memory 
    freeifaddrs(interfaces); 
    return address; 
} 
+1

Premier test à faire - voyez-vous le paquet sur le fil ou non (en supposant que vous exécutez le code de l'émetteur/récepteur sur deux boîtes). Cela permettra de réduire la moitié de la zone à enquêter. Vous pouvez utiliser tcpdump ou wireshark. –

Répondre

3

Dans l'auditeur, je pense que vous devez définir

listeningMc_req.imr_interface.s_addr = htonl(INADDR_ANY); 

... puisque c'est aussi l'interface sur laquelle vous liez la prise. Selon que vous exécutez tout sur un seul hôte, vous devrez peut-être envisager l'interface de bouclage et la liaison à INADDR_ANY le fera.

+0

Ouais, tu as raison ... c'est supposé être comme tu l'as dit. J'avais déjà rencontré ce problème potentiel plus tôt mais je n'ai jamais réussi à éditer la question pour le moment ... C'est réglé maintenant. –

1

Y a-t-il un routeur entre vous et votre destination? Si tel est le cas, un travail doit être fait pour indiquer au routeur que vous souhaitez vous abonner au flux et indiquer au routeur que vous allez envoyer le flux.

Je commencerai par tcpdump-la connexion pour s'assurer que le paquet quitte votre machine en premier.