您的位置:首页 > 运维架构 > Linux

Linux多播技术的使用和编程

2013-09-04 17:36 246 查看
多播技术(Multicast)常常用来编制分布式的聊天、流体音频,和视频等等应用程序。在Linux中使用多播技术,与使用UDP给单个用户发送消息,没有多大的区别,只是你要使用一个特殊的多播IP地址,还有一些环境需要改变一下。  一般的网卡,都是支持多播技术的,但是操作系统不一定。Linux一般在缺省状态编译时,可能都不支持Multicast,你需要从新配置和编译你的内核,使它支持多播,然后你需要使用类似这样的命令:route add -net 224.0.0.0 netmask 240.0.0.0
dev lo  要编译和配置内核,只是在配置的网络部分选项中选中:enable multicast ip,然后编译,编辑lilo的配置文件lilo.conf,就可以搞定。  在使用多播技术时,除了通常使用的socket函数外,还需要使用getsockopt()和setsockopt() 来支持multicast。你可以运行“man multicast”,看看它的各种选项。编制多播的程序,也分为两方面,一个是broadcast data的服务程序,另一个是监听multicast ip 广播数据的客户端程序。  服务程序的编制和普通UDP服务程序的编制一样,只是在你的sockaddr_in结构的初始化时,赋值给它的sin_addr。s_addr使用inet_addr("224.0.0.1")给一个特殊的Muticast
IP值就可以了。  在客户端的编制方面,相对复杂一点。一般我们需要先使用gethostbyname,得到服务器的信息。然后使用socket(AF_INET,SOCK_DGRAM,0)建立套接字,我们接着调用 setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&share,sizeof(share)),其中,char share = 1, sockfd是socket建立的套接字,这一步就是允许了多进程共享同一个端口。接着,是通用的bzero(), 给sockaddr_in填入信息,bind(),下来,我们要通知Linux
kernel来的数据是广播数据,这一步通过给optval付值来搞定,如 optval.imr_multiaddr.s_addr = inet_addr("224.0.0.1"); optval.imr_interface.s_addr = htonl(INADDR_ANY); 先面的这一步,则用来使自己的主机加入一个广播组: setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &optval, sizeof(command)); 现在,你可以使用recvfrom()来接收多播数据了,当然,最后你还要使用:
setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &optval, sizeof(optval)); 来退出多播组。

多播广播是用于建立分步式系统:例如网络游戏、ICQ聊天构建、远程视频会议系统的重要工具。使用多播广播的程序和UDP向单个介绍方发送信息的程序相似。区别在于多播广播程序使用特殊的多播IP地址。

例如本地计算机的的IP地址是:127.0.0.1二它的多播地址是: 224.0.0.1。这是由RCF 1390定义的。为发送IP多播数据,发送者需要确定一个合适的多播地址,这个地址代表一个组。IPv4多播地址采用D类IP地址确定多播的组。在 Internet中,多播地址范围是从224.0.0.0到234.255.255.255。其中比较重要的地址有:
  224.0.0.1 - 网段中所有支持多播的主机
  224.0.0.2 - 网段中所有支持多播的路由器
  224.0.0.4 - 网段中所有的DVMRP路由器
  224.0.0.5 - 所有的OSPF路由器
  224.0.0.6 - 所有的OSPF指派路由器
  224.0.0.9 - 所有RIPv2路由器
  IPv6地址空间中有1/256的地址空间分配给多播地址。一个FF(11111111)值标识该地址是多播地址。标识段高三位始终设置为0并 保留。第四位T标识设置为0时表示一个永久分配的多播地址。T标识设置为1时,表示非永久分配的多播地址,这种地址作为一个临时的多播地址。

注: 在linux下调试时可能需要用root用户登入.

一、配置Linux支持多播IP
  在默认状态下,大多Linux发行版本关闭的对多播IP的支持。为了在Linux系统使用多播套接口,需要从新配置和编译Linux内核。下面看一下配置步骤:
  1.cd /usr/src/linux
  2.make menuconfig
  3.选择网络选项
  4.选中IP:Enable Multicasting IP一项
  5.保存并从menuconfig 退出
  6.运行:make dep;make clean;make bzlmage
  7.cp/vmlinuz/vdimLz_good
  8.cparch/i386/boot/zImage/vmlinzz
  9.cd/etc
  10.编辑lilo.conf,加入针对/vmlinuz_good的内核新选项
  11.运行li1o
  Linux内核编译后,以超级用户身份运行命令: #router add –net 224.0.0.0 netmask 224.0.0.0 dev lo
  核实命令是否加入系统,运行命令:

#route –eKernel IP routing table

Destination gatewary Genmask Flags MSS Window irtt Iface

10.0.0.0 * 255.255.255.0 U 0 0 0 eth0

127.0.0.0 * 255.0.0.0 U 0 0 0 lo

BASE_ADDRESS>MC * 240.0.0.0 U 0 0 0 lo

Default 10.0.0.1 0.0.0.0 UG 0 0 0 eth0
  其中出现多播地址: 224.0.0.1。就表示配置成功了。

  二、使用Linux多播IP广播数据

  1、首先在服务器端建立多播程序:
  服务器端程序代码和解释:broadcast.c
#include <stdio.h>

#include <sys/socket.h>

#include <errno.h>

#include <unistd.h>

#include <string.h>

#include <stdlib.h>

#include <netdb.h>

int port = 6789;

int main(int argc, char **argv)

{

int socketfd;

struct sockaddr_in address;

socketfd = socket(AF_INET, SOCK_DGRAM, 0);

if (-1 == socketfd)

{

perror("Opening socket");

exit(EXIT_FAILURE);

}

memset(&address, 0, sizeof(address));

address.sin_family = AF_INET;

address.sin_addr.s_addr = inet_addr("224.0.0.1");

address.sin_port = htons(port);

//starting Mcast transmit...

while(1)

{

if (sendto(socketfd, "test from broadcast", sizeof("test from broadcast"), 0,(struct sockaddr *)&address, sizeof(address)) < 0)

{

perror("sendto");

exit(EXIT_FAILURE);

}

sleep(2);

}

exit(EXIT_SUCCESS);

}

  2、创建Linux客户端的程序多播IP广播
  建立好广播服务器后,就需要一个客户端的收听程序,收听多播IP广播要求在程序中作以下几项工作:
  (1)、多播方收听,客户端编写通知Linux内核每个指定的套接口加入多播IP广播组。
  (2)、收听方必须运行在同一个Linux计算机的不同进程的同一个套接口。
  (3)、编写配置端口设定广播信息可以发送给同一个Linux主机,这样作的用处是在同一个Linux主机上测试广播程序和收听程序,易于调试。
  客户端程序代码和解释:

#include <stdio.h>

#include <sys/socket.h>

#include <errno.h>

#include <unistd.h>

#include <string.h>

#include <stdlib.h>

#include <netdb.h>

char *host_name = "224.0.0.1";

int port = 6789;

int main(int argc, char **argv)

{

int socketfd;

struct sockaddr_in sin;

struct ip_mreq command;

int loop = 1, iter = 0, sin_len;

struct hostent *server_host_name;

char message[256];

if ((server_host_name = gethostbyname(host_name)) == 0)

{

perror("gethostbyname");

exit(EXIT_FAILURE);

}

socketfd = socket(AF_INET, SOCK_DGRAM, 0);

if (-1 == socketfd)

{

perror("Opening socket");

exit(EXIT_FAILURE);

}

memset(&sin, 0, sizeof(sin));

sin.sin_family = AF_INET;

sin.sin_addr.s_addr = htonl(INADDR_ANY);

sin.sin_port = htons(port);

loop = 1;

if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &loop, sizeof(loop)) < 0)

{

perror("setsockopt: SO_REUSEADDR");

exit(EXIT_FAILURE);

}

if (bind(socketfd, (struct sockaddr *)&sin, sizeof(sin)) < 0)

{

perror("bind");

exit(EXIT_FAILURE);

}

loop = 1;

if (setsockopt(socketfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0)

{

perror("setsockopt: IP_MULTICAST_LOOP");

exit(EXIT_FAILURE);

}

command.imr_multiaddr.s_addr = inet_addr("224.0.0.1");

command.imr_interface.s_addr = htonl(INADDR_ANY);

if (command.imr_multiaddr.s_addr == -1)

{

perror("224.0.0.1 not a legal multicast address.");

exit(EXIT_FAILURE);

}

if (setsockopt(socketfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &command, sizeof(command)) < 0)

{

perror("setsockopt: IP ADD_MEMBERSHIP");

}

while(iter < 8)

{

sin_len = sizeof(sin);

if (recvfrom(socketfd, message, 256, 0, (struct sockaddr *)&sin, &sin_len) == -1)

{

perror("recvfrom");

}

printf("Response #%-2d from server: %s\n", iter++, message);

sleep(2);

}

if (setsockopt(socketfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &command, sizeof(command)) < 0)

{

perror("setsockopt: IP_DROP_MEMBERSHIP");

}

close(socketfd);

exit(EXIT_SUCCESS);

}

  3、运行Linux多播IP程序

  运行程序,打开两个终端窗口并在每个窗口中输入以上的源代码。在一个窗口中键入make,编译 broadcast和1isten这两个的可执行文件,由GUN make建立一个Makfiles文件。GUN make是Linux系统中一个自动生成和维护目标程序的工具。
  在一个窗口中通过执行./broadcast,在另一个的窗口执行./listen,启动收听程序,你应该看到如下输出:

#./listenResponse #1 form sever :test from broadcast

Response #2 form sever :test from broadcast

Response #3 form sever :test from broadcast

Response #4 form sever :test from broadcast

Response #5 form sever :test from broadcast

Response #6 form sever :test from broadcast

Response #7 form sever :test from broadcast

Response #8 form sever :test from broadcast

#

 4、总结
  Linux多播IP是一种同时向价格进程高效的发送信息的介绍。多播传输中,数据被发送到接收者的多播地址,而不是每个接收者的单播地址,发送者只发送一个数据拷贝,源端到目标端路径上的中间节点复制该数据。现在多播IP已经广泛应用于网络游戏、视频广播的领域
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: