2012-06-21 13 views
5

多くのアプリケーションにローカルでメッセージをブロードキャストしたい。そのために私はUDPソケットが最高のIPCだと思っていました。聞くためにブロードキャスト方法UDPソケットを使ってメッセージをローカルにブロードキャストするには?

/* 
** 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のようにIPを渡す必要があるということです.1.255しかし実際のシナリオではeth0インターフェイスがないかもしれませんが、ループバックだけがあります。それではどうしたらいいですか?

答えて

7

サーバーは、getaddrinfoから取得したアドレスにバインドしないでください。代わりに、127.255.255.255(ループバックインターフェイス用)にバインドする必要があります。放送サーバ/クライアントの既製例えば

http://www.ccplusplus.com/2011/09/udp-broadcast-client-server-example.html

+0

私はその例を何度も試してみましたが、実行中は常に「成功:不正なサーバーアドレス」を取得しています。 – Yuvi

3

UNIXドメインソケットはマルチ/ブロードキャストをサポートしていません。

ローカルインターフェイス127.0.0.1でブロードキャストできます。

+0

を参照してくださいはい、私はちょうど掲示した後、これを見つけたので、私はちょうど常に存在するローカルインタフェースを使用し、 – Yuvi

+0

更新..私の質問を編集しました。 –

+0

この場合、1つのクライアントのみで聴くことができます。 – Yuvi

関連する問題