在掌握了多播的相关基础后,本文我们通过实例来演示如何让你的进程加入多播组。
1. 程序路径
本文使用的程序托管在 gitos 上:http://git.oschina.net/ivan_allen/unp
本文使用的程序路径为 unp/program/multicast/basic
.
2. 客户端
udp 客户端部分无需做任何更改,在指定目标 ip 地址的时候,直接使用多播地址。意思是说,向这个“QQ群”发信息。
3. 服务器
udp 服务器相对于之前的区别就是加入一个多播组,所以这里关键是如何加入多播组的问题。下面是具体程序,关键的地方已做注释。
void server_routine() {
int ret, sockfd;
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddrlen;
// 加入多播组要填充的结构体
struct ip_mreq mreq;
ret = resolve(g_option.hostname, g_option.port, &servaddr);
if (ret < 0) ERR_EXIT("resolve");
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) ERR_EXIT("socket");
// 绑定本地接口,默认为 INADDR_ANY
ret = bind(sockfd, (struct sockaddr*)&servaddr, sizeof servaddr);
if (ret < 0) ERR_EXIT("bind");
// “构造QQ群号”:填充要加入的多播组地址,比如 230.2.2.2
mreq.imr_multiaddr.s_addr = inet_addr(g_option.multiAddr);
// “指定要加入QQ群的QQ号”:指定哪个接口(网卡出口)加入多播组
mreq.imr_interface.s_addr = servaddr.sin_addr.s_addr;
// “加入QQ群”:调用 setsockopt 函数,将网卡出口加入指定的多播组
ret = setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
if (ret < 0) ERR_EXIT("setsockopt:IP_ADD_MEMBERSHIP");
LOG("multicast group: %s\n", g_option.multiAddr);
doServer(sockfd);
// “退群”:将网卡接口移出多播组
ret = setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
if (ret < 0) ERR_EXIT("setsockopt:IP_DROP_MEMBERSHIP");
close(sockfd);
}
上面的程序非常简单,一旦有多个服务器加入了同一个多播组,客户端向此多播组发送信息,所有的服务器都能收到信息。
4. 相关的套接字选项(IPv4)
再看完第 3 小节的程序后,有必要对相关的套接字选项做介绍。Linux/Unix 提供了很多套接字选项用来操作多播。
选项名 | 数据类型 | 说明 |
---|---|---|
IP_MULTICAST_IF | struct in_addr | 发送多播数据报时,指定外出接口 |
IP_MULTICAST_TTL | u_char | 指定外出多播数据报的 TTL |
IP_MULTICAST_LOOP | u_char | 开启或禁止外出多播数据报回环 |
选项名 | 数据类型 | 说明 |
---|---|---|
IP_ADD_MEMBERSHIP | struct ip_mreq | 加入一个多播组 |
IP_DROP_MEMBERSHIP | struct ip_mreq | 离开一个多播组 |
表 1 和表 2 只列举了一部分,还有一些,暂时不例举。上面列举的,都是我们目前能看懂的。在第 3 节的例子中,已经演示了 IP_ADD_MEMBERSHIP 和 IP_DROP_MEMBERSHIP 的用法。
5. 实验
在 flower 主机和 moon 主机上启动两个 UDP 多播服务器,多播地址是230.2.2.2,端口号是 7777,然后在 moon 主机上启动 UDP 客户端,向组 230.2.2.2 发信息。
- 启动 udp 服务器
// 默认组地址是 230.2.2.2,所以 -g 选项可以不用写
$ ./mc -s -p 7777 -g 230.2.2.2
- 启动客户端
$ ./mc -h 230.2.2.2
- 运行结果
图1 客户端
图2 moon 主机上的服务器
图3 flower 主机上的服务器
6 总结
- 掌握如何加入一个组