linux下的多播

来源:互联网 发布:惠普打印机驱动for mac 编辑:程序博客网 时间:2024/04/20 01:08


进行Linux下的多播编程时,需要关闭防火墙,关闭防火墙的方法如下:

1) 重启后生效
开启: chkconfig iptables on
关闭: chkconfig iptables off

2) 即时生效,重启后失效
开启: service iptables start
关闭: service iptables stop

 

服务器端代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>

int main()
{
 int sockfd;
 sockfd = socket(AF_INET, SOCK_DGRAM, 0);//UDP协议的套接字
 if (-1 == sockfd)
 {
  perror("socket");
  exit(1);
 }
 
 struct sockaddr_in address;
 memset(&address, 0, sizeof(address));
 address.sin_family = AF_INET;
 address.sin_addr.s_addr = inet_addr("224.0.0.99");//多播组地址
 address.sin_port = htons(6789);//多播组端口号
 
 while(1)
 {
     char buf[] =  "test from broadcast";
  //向多播组机器的6789号端口发送消息
  if (sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&address, sizeof(address)) < 0)
  {
   perror("sendto");
   close(sockfd);
   exit(1);
  }
 
  struct sockaddr_in sin;
  int sin_len = sizeof(sin);
  char message[256];
  if (recvfrom(sockfd, message, 256, 0, (struct sockaddr *)&sin, &sin_len) == -1)
  {
   perror("recvfrom");
   close(sockfd);
   exit(1);
     }
  printf("%s %s/n", inet_ntoa(sin.sin_addr.s_addr), message);
  sleep(2);
 }
 
 exit(0);
}


客户端代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>

int main(void)
{
 //判断指定的多播地址是否有效
 char *host_name = "224.0.0.99";//多播组的地址
 if (0 == gethostbyname(host_name))
 {
  perror("gethostbyname");
  exit(1);
 }
 
 //UDP套接字
 int sockfd;
 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
 {
  perror("socket");
  exit(1);
 }
 
 struct sockaddr_in sin;
 memset(&sin, 0, sizeof(sin));
 sin.sin_family = AF_INET;
 /*不管是绑定本机的IP还是绑定组播地址,效果都是一样,服务器端接收数据时
 看到的都是本机的IP地址,不会是多播地址。*/
 //sin.sin_addr.s_addr = htonl(INADDR_ANY);//可以绑定本机的所有IP
 sin.sin_addr.s_addr = inet_addr("224.0.0.99");//也可以绑定组播地址(要加入的组播地址)
 //sin.sin_addr.s_addr = inet_addr("224.0.0.88");//不可以是其他的组播地址!
 sin.sin_port = htons(6789);//本机的端口号
 
 //地址复用
 const int on = 1;
 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
 {
  perror("setsockopt:SO_REUSEADDR");
  exit(1);
 }
 
 //发送消息时也会给自己发送一份,是否设置不影响多播的发送与接收
 if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &on, sizeof(on)) < 0)
 {
  perror("setsockopt:IP_MULTICAST_LOOP");
  exit(1);
 }
 
 //套接字绑定,注意套接字的端口号是6789
 if (bind(sockfd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
 {
  perror("bind");
  exit(1);
 }
 
 //需要把本机的哪个IP添加到多播组
 struct ip_mreq command;
 command.imr_multiaddr.s_addr = inet_addr(host_name);//多播组地址
 command.imr_interface.s_addr = htonl(INADDR_ANY);//本机的所有地址
 //command.imr_interface.s_addr = inet_addr("224.0.0.99");//不能使用组播地址,否则加入多播组会出错!
 if (-1 == command.imr_multiaddr.s_addr)
 {
  perror("224.0.0.99 not a legal multicast address");
  exit(1);
 }
 //加入多播组224.0.0.99
 if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &command, sizeof(command)) < 0)
 {
  perror("setsockopt:IP_ADD_MEMBERSHIP");
 }
 
 int iter = 0;
 int sin_len;
 char message[256];
 
 while(iter++ < 8)
 {
  sin_len = sizeof(sin);
  //接收消息
  if (recvfrom(sockfd, message, 256, 0, (struct sockaddr *)&sin, &sin_len) == -1)
  {
   perror("recvfrom");
   close(sockfd);
   exit(1);
     }
  printf("Response #%-2d from server: %s/n", iter, message);
 
  char buf[] = "Bye";
  if (sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&sin, sin_len) == -1)
  {
      perror("sendto");
   close(sockfd);
   exit(1);
  }
  sleep(2);
 }
 
 //退出多播组224.0.0.99
 if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,&command, sizeof(command)) < 0)
 {
  perror("setsockopt:IP_DROP_MEMBERSHIP");
 }
 
 close(sockfd);//关闭套接字
 
 exit(1);
}