Pergunta

Ok, se você olhar para algumas das minhas perguntas anteriores, eu estive trabalhando para conseguir uma simples conexão instalado e funcionando com soquetes C (eu ainda sou bastante novo para todo o aspecto de rede de um programa, mas todo mundo tem começar em algum lugar, certo?). Eu incluí o código abaixo que eu tenho até agora e quando eu executá-lo, eu recebo nenhum erro, mas, ao mesmo tempo, eu não receber o pacote na outra extremidade. By the way, eu estou programando soquetes multicast em Objective-C e "msgStatus" é apenas um rótulo na minha GUI (é ligado corretamente, então não há nenhum problema). Eu apenas não estou vendo onde estou indo errado. Alguém poderia possivelmente me ajudar ou me aponte na direção certa? Obrigado!

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

Aqui está o código que estou usando para extrair meu endereço 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; 
}
Foi útil?

Solução

No ouvinte, eu acho que você precisa set

listeningMc_req.imr_interface.s_addr = htonl(INADDR_ANY);

... uma vez que é também a interface em que você vincular o socket. Dependendo se você executar tudo em um único host, você pode precisar de considerar a interface de auto-retorno e ligação a INADDR_ANY vai fazer isso.

Outras dicas

Existe um roteador entre você e seu destino? Se assim for, há algum trabalho que precisa ser feito para dizer ao roteador que você deseja assinar o feed, bem como informar ao roteador que você vai ser o envio do feed.

Gostaria de começar por-tcpdump ing a conexão para garantir que o pacote está deixando a sua máquina pela primeira vez.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top