代码之家  ›  专栏  ›  技术社区  ›  Josh Bradley

发送/接收UDP数据包的帮助-C套接字

  •  3
  • Josh Bradley  · 技术社区  · 17 年前

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

    这是我用来提取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; 
    }
    
    2 回复  |  直到 17 年前
        1
  •  3
  •   VoidPointer    17 年前

    在听众中,我认为你需要设置

    listeningMc_req.imr_interface.s_addr = htonl(INADDR_ANY);
    

    ... 因为这也是绑定套接字的接口。根据您是否在单个主机上运行所有内容,您可能需要考虑环回接口,并将其绑定到INADDR_ANY。

        2
  •  1
  •   ProZach    17 年前

    首先,我将tcpdump连接,以确保数据包首先离开您的机器。

    推荐文章