应用程序通过
命令字IP_ADD_MEMBERSHIP把一个socket加入到一个多播组,IP_ADD_MEMBERSHIP是一个IP层的命令字,其调用使用的参数是结构体struct ip_mreq,其定义如下: struct ip_mreq { struct in_addr imr_multiaddrstruct in_addr imr_interf...这就要有PIM(Protocol Independent Multicast,
协议无关组播组)协议的支持,就必须在Linux环境下安装Pimd软件协议包。 安装补丁文件 安装Pimd软件协议包需要两个补丁文件:pimkern-freebsd-4.6.patch和netstat-freebsd-4.6.patch。安装步骤如下: 首先将两个补丁文件拷贝到/usr/src/目录下,并
执行以下命令:#patch -p2 <netstat-freebsd-4.6.patch #patch -p2 <pimkern-freebsd-4.6.patch 执行以下命令,编译并安装netstat:#cd /usr/src/usr.bin/netstat #make #make install 重新编译内核 执行以下命令,修改multi配置文件:#cd /usr/src/sys/i386/conf/ #cp GENRIC multi #vi multi 在multi配置文件中,加入下列两行代码:options MROUTING options PIM 保存并退出vi编辑器。 在当前multi配置文件所在的目录执行以下命令:#config multi #cd /usr/src/sys/compile/multi/ #make depend #make #make install 至此,新内核编译完毕。 备份Kernel文件 新内核编译完毕后,在重新启动前,要先将根目录下原有的Kernel文件进行备份。#cd / #mv kernel kernel.old 若提示“operation not permitted”,则需要先执行以下命令:#chflags noschg /kernel 备份Kernel文件后执行以下命令:#cp /usr/src/sys/compile/multi/kernel /kernel 在系统重新启动后,默认选择的便是新编译的内核。 安装Pimd软件协议包 Linux下Pimd软件协议包代码的起源有两个地方,一个是日本的KAME项目组,另一个是南加州大学信息科学学院。到这两个组织的主页上都可以下载所需要的pimd-current.tar.gz 协议包和上面提到的两个补丁。 用以下命令解压缩 pimd-current.tar.gz 软件包,并安装:#tar zxf pimd-current.tar.gz #cd pimd-2.1.0-alpha29.16 #make #make install 以上命令执行过程中可能会出现错误,需要手工将其完成,拷贝当前目录下的pimd文件:#cp pimd /usr/local/bin/ #chmod 755 pimd #cp pimd.conf /etc/ 至此,Pimd软件协议包安装完毕。还需要打开Linux系统的路由转发功能,才能实现组播包的转发,即在配置文件rc.conf中增加以下代码,重启后生效。作者:龙宇翔 苑庆国socket创建UDP通信描述符后,setsockopt加入多播组,再bind绑定到该网卡上
//在指定的IP和端口上接收多播组的报文
int recv_msg(char *ip , unsigned short port , char *mult_ip )
{
//建立通讯套接字
int fd = socket( PF_INET , SOCK_DGRAM , 0 )
if( -1 == fd )
{
perror("socket failed")
return -1
}
//设置地址重用和接收多播
{
int reuse = 1
struct ip_mreqn mult_addr = {0}
mult_addr.imr_multiaddr.s_addr = inet_addr( mult_ip )
mult_addr.imr_address.s_addr = inet_addr( ip )
if( -1 == setsockopt( fd , IPPROTO_IP , IP_ADD_MEMBERSHIP ,
&mult_addr , sizeof(mult_addr)))
{
perror("setsockopt add failed")
goto _out
}
if( -1 == setsockopt( fd , SOL_SOCKET, SO_REUSEADDR,
&reuse , sizeof(reuse) ) )
{
perror("setsockopt reuse failed")
}
}
//绑定地址和端口
{
struct sockaddr_in addr = {0}
addr.sin_family = PF_INET
addr.sin_port = htons( port )
addr.sin_addr.s_addr = INADDR_ANY
if( -1 == bind( fd , (struct sockaddr*)&addr ,
sizeof(addr) ) )
{
perror("bind failed")
goto _out
}
}
//接收信息
while(1)
{
char buf[128] = {0}
int ret = 0
struct sockaddr_in client_addr = {0}
int len = sizeof(client_addr)
ret = recvfrom( fd , buf , sizeof(buf), 0 ,
(struct sockaddr*)&client_addr ,
&len )
//被信号中断则重启
if( (-1 == ret)&&(EINTR ==errno ))
{
continue
}
else if( -1 ==ret )
{
perror("recvfrom failed")
goto _out
}
else if( ret >0 )
{
printf("%s\n" , buf )
}
usleep( 100*1000 )
}
_out:
if( fd >= 0)
{
close( fd )
}
return 0
}
评论列表(0条)