107-使用多播的 UDP C/S 程序

在掌握了多播的相关基础后,本文我们通过实例来演示如何让你的进程加入多播组。

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 提供了很多套接字选项用来操作多播。

表1 组成员无关多播套接字选项

选项名 数据类型 说明
IP_MULTICAST_IF struct in_addr 发送多播数据报时,指定外出接口
IP_MULTICAST_TTL u_char 指定外出多播数据报的 TTL
IP_MULTICAST_LOOP u_char 开启或禁止外出多播数据报回环

表2 组成员相关多播套接字选项

选项名 数据类型 说明
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 总结

  • 掌握如何加入一个组