views:

1911

answers:

2

Ok, if you look at some of my previous questions, I've been working on getting a simple connection up and running with C sockets (I'm still fairly new to the whole networking aspect of an program, but everyone has to start somewhere, right?). I've included the code below that I have so far and when I execute it, I get no errors, but at the same time, I don't get the packet on the other end. By the way, I'm programming multicast sockets in objective-C and "msgStatus" is just a label in my GUI (it's hooked up correctly, so there's no problem there). I'm just not seeing where I'm going wrong. Could someone possibly help me or point me in the right direction? Thanks!

#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"); 
}

Here is the code I'm using to extract my IP Address.

-(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; 
}
A: 

Is there a router between you and your destination? If so, there's some work that needs to be done to tell the router that you want to subscribe to the feed as well as tell the router you will be sending the feed.

I would start by tcpdump-ing the connection to make sure the packet is leaving your machine first.

ProZach
A: 

In the listener, I think you need to set

listeningMc_req.imr_interface.s_addr = htonl(INADDR_ANY);

... since that is also the interface on which you bind the socket. Depending on whether you run everything on a single host, you might need to consider the loopback interface and binding to INADDR_ANY will do that.

VoidPointer
Yeah, you're right...it's supposed to be like you said. I had actually caught that potential problem earlier but never got around to editing the question yet...It's fixed now.
Josh Bradley