linux 下的组播编程

 

组播

组播通过测试,双网卡或多网卡设置在不同IP段。

IP地址空间被划分为A、B、C三类。第四类即D类地址被保留用做组播地址。在第四版的IP协议(IPv4)中,从224.0.0.0到239.255.255.255间的所有IP地址都属于D类地址。所以要利用组播发送数据必须有一个虚拟的组播IP,所谓虚拟,就是你不必把网卡地址设为此IP,而只需在你程序中出现,相当于建立一个以此IP为标志的集合,所有想加入组播的必须加入这个集合之中,发送组播时,往此IP发送,所有此集合中的主机均可接收到相同的数据,其处理转发过程由上一级路由器或者集线器处理。一台主机可以加入到多个组播组之中,一个组播组可以含有多台主机,但是这些主机必须在同一IP段,即在同一个路由之下。

下面一个程序可以实现UDP组播的客户端部分的接收。

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/select.h>
#include <netinet/in.h>

char group_ip[] = "226.0.0.1";      //组播IP地址

char local_IP[] = "192.168.6.208";     //本机IP地址

int local_port = 26001;                   //端口号

 

 

/*
*group_ip 组播地址
*local_ip   本机的实际地址

*port  组播端口号
*/
int Init_Socket(char *group_ip, char *local_ip, short port)
{
 int sockfd;
 unsigned long seladdr;
 int  addr_len;
 struct ip_mreq group_mreq;
 struct sockaddr_in group_addr;
 struct sockaddr_in local_addr;

 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
     printf("***********************socket error *****************\n");
      return 0;
    }
 addr_len = sizeof (struct sockaddr_in);
 memset(&local_addr, 0, sizeof(local_addr));
 local_addr.sin_family = AF_INET;
 local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 local_addr.sin_port = htons(port);
 if(bind(sockfd,(struct sockaddr *)&local_addr, addr_len) < 0)
    {
     printf("***********************bind error ********************\n");
      return 0;
    }

 /*将本地IP绑定到相应组播上,经过测试,如果只有一块网卡,或者有多快网卡,只是用第一块(默认的)可以不设置,但是如果有多块网卡,或者使用多块网卡中的非默认的,必须绑定*/
  seladdr = inet_addr(local_ip);
  if(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF,(char *)&seladdr, sizeof(seladdr)) < 0)
   {  
    printf("***********************setsockopt:IP_MULTICAST_LOOP***********************\n");
     return 0;
   }

 /* 加入一个组播组,支持组播,进一步告诉Linux内核,特定的套接口即接受广播数据*/
  group_mreq.imr_multiaddr.s_addr = inet_addr(group_ip);
  group_mreq.imr_interface.s_addr = inet_addr(local_ip);
  if(group_mreq.imr_multiaddr.s_addr == -1)
 { 
   perror("224.0.0.1 not a legal multicast address");
  return 0;
 }
   if(setsockopt(sockfd , IPPROTO_IP, IP_ADD_MEMBERSHIP,&group_mreq, sizeof(group_mreq)) < 0)
  {  
    perror("setsockopt:IP_ADD_MEMBERSHIP\n");
  return 0;
  }
 return sockfd;
}

 

int wait_for_read(int socket, int seconds)

 int flag; 
 fd_set fds; 
 struct timeval timeout; 

 FD_ZERO(&fds); 
 FD_SET(socket, &fds); 
 timeout.tv_sec = seconds; 
 timeout.tv_usec = 0;  
 flag = select(socket + 1, &fds, NULL, NULL, &timeout);  
 if (flag > 0 && FD_ISSET(socket, &fds))
 {
  return 1;
 }
 printf("flag = %d status = %d \n", flag, FD_ISSET(socket, &fds));
 return 0;
}

int main()
{
    int  ret;
   int  sFd1;
  sFd1 = Init_Socket(group_ip, local_ip, port);

/* 循环接受用户输入的消息发送组播消息 */
 while(1)
 {
  if (wait_for_read(sFd1, 2) == 1)
  {
   //recv msg   

  } 
 }

//结束

close(sFd1);

return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值