使用多播地址和组

时间:2014-03-13 18:04:50

标签: sockets networking udp multicast

在一周左右的时间里,我一直在研究从单一来源向多个客户端发送数据报的方法,并发现IP支持224.0.0.0234.255.255.255范围内的多播。我已经阅读了一些描述该技术的文档,但是我找不到任何有助于我理解如何使用它们的文档。

根据我收集的信息,程序似乎要求操作系统内核加入非关联的组播组,然后开始通过UDP将数据通过UDP发送到组播地址。其他所有内容都由WAN处理,而不需要在发送到的地址上进行任何物理处理。

这一思路已被我所读过的内容模糊地支持,但尚未得到证实。这个想法是否正确?如果有问题会有什么问题?

1 个答案:

答案 0 :(得分:1)

这基本上是正确的。

在接收方,首先打开一个侦听特定端口的套接字。然后,您在给定的网络接口上加入多播地址。这样做会导致操作系统向网络发送IGMP消息,通知正在加入组的路由器。

在发件人方面,打开套接字,然后为多播配置传出网络接口。完成后,您可以将数据包发送到任何多播地址。

以下是C中的示例发件人:

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

int main(int argc, char *argv[])
{
  struct sockaddr_in sin;
  struct in_addr out_addr;
  char mes[255], ttl;
  int sock;

  printf("Enter message: ");
  fgets(mes, sizeof(mes), stdin);
  bzero(&sin,sizeof(sin));
  sin.sin_family=AF_INET;
  sin.sin_addr.s_addr=inet_addr(argv[1]);
  sin.sin_port=htons(atoi(argv[2]));
  if ((sock=socket(AF_INET,SOCK_DGRAM,0))==-1) {
    perror("Error creating socket");
    exit(1);
  }
  out_addr.s_addr=inet_addr(argv[3]);
  if (setsockopt(sock,IPPROTO_IP,IP_MULTICAST_IF,(char *)&out_addr,sizeof(out_addr))== -1) {
    perror("Error setting outgoing interface");
    close(sock);
    exit(1);
  }
  if (sendto(sock,mes,strlen(mes),0,(struct sockaddr *)&sin,sizeof(sin))==-1) {
    close(sock);
    perror("Send error");
  }
  close(sock);
}

这是C中的示例接收器:

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
  int addr_len;
  struct sockaddr_in sin,sin_recv;
  struct ip_mreq multi;
  char mes[255];
  int sock;

  bzero(&sin,sizeof(sin));
  multi.imr_multiaddr.s_addr=inet_addr(argv[1]);
  multi.imr_interface.s_addr=inet_addr(argv[2]);
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = INADDR_ANY;
  sin.sin_port = htons(atoi(argv[3]));
  if ((sock=socket(AF_INET,SOCK_DGRAM,0))==-1) {
    perror("Error creating socket");
    exit(1);
  }
  if (setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char *)&multi,sizeof(multi))== -1) {
    perror("Error joining multicast group");
    close(sock);
    exit(1);
  }
  if (bind(sock,(struct sockaddr *)&sin,sizeof(sin))==-1) {
    perror("Error binding socket");
    close(sock);
    exit(1);
  }
  while (1) {
    bzero(mes,sizeof(mes));
    bzero(&sin_recv,sizeof(sin_recv));
    addr_len=sizeof(sin_recv);
    printf("Waiting for packet...\n");
    if (recvfrom(sock,mes,sizeof(mes),0,(struct sockaddr *)&sin_recv,&addr_len)==-1) {
      perror("error recving socket");
      close(sock);
      exit(1);
    }
    printf("Got packet\n");
    printf("Origin: %s port %d\n",inet_ntoa(sin_recv.sin_addr),sin_recv.sin_port);
    printf("Message: %s\n",mes);
  }
}