2012-06-21 7 views
5

मैं कई एप्लिकेशन में स्थानीय रूप से संदेशों को प्रसारित करना चाहता हूं। इसके लिए मैंने सोचा कि यूडीपी सॉकेट सबसे अच्छा आईपीसी है, अगर मैं परेशान हूं तो मुझे सही करें।स्थानीय रूप से यूडीपी सॉकेट का उपयोग करके संदेश कैसे प्रसारित करें?

इसके लिए मैं निम्नलिखित कोड का उपयोग कर रहा हूँ:

प्रसारण के लिए:

/* 
** broadcaster.c -- a datagram "client" that can broadcast 
*/ 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

#define SERVERPORT 4950 // the port users will be connecting to 

int main(int argc, char *argv[]) 
{ 
    int sockfd; 
    struct sockaddr_in their_addr; // connector's address information 
    struct hostent *he; 
    int numbytes; 
    int broadcast = 1; 
    //char broadcast = '1'; // if that doesn't work, try this 

    if (argc != 3) { 
     fprintf(stderr,"usage: broadcaster hostname message\n"); 
     exit(1); 
    } 

    if ((he=gethostbyname(argv[1])) == NULL) { // get the host info 
     perror("gethostbyname"); 
     exit(1); 
    } 

    if ((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) { 
     perror("socket"); 
     exit(1); 
    } 

    // this call is what allows broadcast packets to be sent: 
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, 
     sizeof broadcast) == -1) { 
     perror("setsockopt (SO_BROADCAST)"); 
     exit(1); 
    } 

    their_addr.sin_family = AF_UNIX;  // host byte order 
    their_addr.sin_port = htons(SERVERPORT); // short, network byte order 
    their_addr.sin_addr = *((struct in_addr *)he->h_addr); 
    memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero); 

    if ((numbytes=sendto(sockfd, argv[2], strlen(argv[2]), 0, 
      (struct sockaddr *)&their_addr, sizeof their_addr)) == -1) { 
     perror("sendto"); 
     exit(1); 
    } 

    printf("sent %d bytes to %s\n", numbytes, 
     inet_ntoa(their_addr.sin_addr)); 

    close(sockfd); 

    return 0; 
} 

और सुनने के लिए:

/* 
** listener.c -- a datagram sockets "server" demo 
*/ 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

#define MYPORT "4950" // the port users will be connecting to 

#define MAXBUFLEN 100 

// get sockaddr, IPv4 or IPv6: 
void *get_in_addr(struct sockaddr *sa) 
{ 
    if (sa->sa_family == AF_INET) { 
     return &(((struct sockaddr_in*)sa)->sin_addr); 
    } 

    return &(((struct sockaddr_in6*)sa)->sin6_addr); 
} 

int main(void) 
{ 
    int sockfd; 
    struct addrinfo hints, *servinfo, *p; 
    int rv; 
    int numbytes; 
    struct sockaddr_storage their_addr; 
    char buf[MAXBUFLEN]; 
    socklen_t addr_len; 
    char s[INET6_ADDRSTRLEN]; 
    int optval = 1; 

    memset(&hints, 0, sizeof hints); 
    hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4 
    hints.ai_socktype = SOCK_DGRAM; 
    hints.ai_flags = AI_PASSIVE; // use my IP 

    if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
     return 1; 
    } 

    // loop through all the results and bind to the first we can 
    for(p = servinfo; p != NULL; p = p->ai_next) { 
     if ((sockfd = socket(p->ai_family, p->ai_socktype, 
       p->ai_protocol)) == -1) { 
      perror("listener: socket"); 
      continue; 
     } 

     if(setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR, &optval, sizeof optval) != 0) 
     { 
      perror("listener: setsockopt"); 
      continue; 
     } 

     if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { 
      close(sockfd); 
      perror("listener: bind"); 
      continue; 
     } 

     break; 
    } 

    if (p == NULL) { 
     fprintf(stderr, "listener: failed to bind socket\n"); 
     return 2; 
    } 

    freeaddrinfo(servinfo); 

    printf("listener: waiting to recvfrom...\n"); 

    addr_len = sizeof their_addr; 
    if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, 
     (struct sockaddr *)&their_addr, &addr_len)) == -1) { 
     perror("recvfrom"); 
     exit(1); 
    } 

    printf("listener: got packet from %s\n", 
     inet_ntop(their_addr.ss_family, 
      get_in_addr((struct sockaddr *)&their_addr), 
      s, sizeof s)); 
    printf("listener: packet is %d bytes long\n", numbytes); 
    buf[numbytes] = '\0'; 
    printf("listener: packet contains \"%s\"\n", buf); 

    close(sockfd); 

    return 0; 
} 
समस्या

मैं इस 192.168 तरह आईपी पारित करने के लिए है कि है .1.255 लेकिन वास्तविक परिदृश्य में eth0 इंटरफेस नहीं हो सकता है, केवल लूपबैक होगा। तो मैं इसे कैसे प्राप्त कर सकता हूं?

उत्तर

7

सर्वर को getaddrinfo से प्राप्त पते से बाध्य नहीं होना चाहिए, इसके बजाय इसे 127.255.255.255 (लूपबैक इंटरफ़ेस के लिए) होना चाहिए।

प्रसारण सर्वर के एक पहले से तैयार उदाहरण के लिए/ग्राहक को देखने के http://www.ccplusplus.com/2011/09/udp-broadcast-client-server-example.html

+0

मैंने उस उदाहरण को कई बार कोशिश की है, लेकिन चलते समय मुझे हमेशा 'सफलता: खराब सर्वर पता' मिल रहा है और कुछ भी काम नहीं करता है :( – Yuvi

3

यूनिक्स डोमेन सॉकेट बहु/प्रसारण का समर्थन नहीं करते हैं।

आप स्थानीय इंटरफ़ेस 127.0.0.1 पर प्रसारित कर सकते हैं।

+0

हाँ, मैं सिर्फ इस पोस्ट करने के बाद पाया है, इसलिए मैं अपने सवाल .. – Yuvi

+0

अपडेट किया गया संपादित किया है, सिर्फ स्थानीय इंटरफ़ेस हमेशा मौजूद है का उपयोग करें। –

+0

इस मामले में, मैं केवल एक ग्राहक को सुनने में सक्षम हूं। – Yuvi