转自:http://blog.csdn.net/tennysonsky/article/details/44493407

一、概述

单播用于两个主机之间的端对端通信,广播用于一个主机对整个局域网上所有主机上的数据通信。单播和广播是两个极端,要么对一个主机进行通信,要么对整个局域网上的主机进行通信。实际情况下,经常需要对一组特定的主机进行通信,而不是整个局域网上的所有主机,这就是多播的用途。

IP 多播(也称多址广播或组播)技术,是一种允许一台或多台主机(多播源)发送单一数据包到多台主机(一次的,同时的)的 TCP/IP 网络技术。多播是 IPv6 数据包的 3 种基本目的地址类型之一,多播是一点对多点的通信, IPv6 没有采用 IPv4 中的组播术语,而是将广播看成是多播的一个特殊例子

多播作为一点对多点的通信,数据的收发仅仅在同一分组中进行,是节省网络带宽的有效方法之一。在网络应用中,当需要将一个节点的信号传送到多个节点时,无论是采用重复点对点通信方式,还是采用广播方式,都会严重浪费网络带宽,只有多播才是最好的选择。多播能使一个或多个多播源只把数据包发送给特定的多播组,而只有加入该多播组的主机才能接收到数据包。

IP 多播应用大致可以分为三类: 点对多点应用,多点对点应用和多点对多点应用。

1)点对多点应用是指一个发送者,多个接收者的应用形式,这是最常见的多播应用形式。典型的应用包括:媒体广播、媒体推送、信息缓存、事件通知和状态监视等。

2)多点对点应用是指多个发送者,一个接收者的应用形式。通常是双向请求响应应用,任何一端(多点或点)都有可能发起请求。典型应用包括:资源查找、数据收集、网络竞拍、信息询问等。

3)多点对多点应用是指多个发送者和多个接收者的应用形式。通常,每个接收者可以接收多个发送者发送的数据,同时,每个发送者可以把数据发送给多个接收者。典型应用包括:多点会议、资源同步、并行处理、协同处理、远程学习、讨论组、分布式交互模拟(DIS)、多人游戏

二、多播地址

IP 多播通信必须依赖于 IP 多播地址,在 IPv4 中它是一个 D 类 IP 地址,范围从 224.0.0.0 到 239.255.255.255,并被划分为局部链接多播地址、预留多播地址和管理权限多播地址三类:

1)局部链接多播地址范围在 224.0.0.0~224.0.0.255,这是为路由协议和其它用途保留的地址,路由器并不转发属于此范围的IP包;

2)预留多播地址为 224.0.1.0~238.255.255.255,可用于全球范围(如Internet)或网络协议;

3)管理权限多播地址为 239.0.0.0~239.255.255.255,可供组织内部使用,类似于私有 IP 地址,不能用于 Internet,可限制多播范围。

一些多播组地址被 IANA 确定为知名地址,它们也被当作永久主机组,这和 TCP 及 UDP 中的知名端口相似。同样,这些知名多播地址在 RFC 最新分配数字中列出,注意这些多播地址所代表的组是永久组,而它们的组成员却不是永久的。这些地址如下:

224.0.0.1    所有组播主机

224.0.0.2    所有组播路由器

224.0.0.4    DRMRP 路由器

224.0.0.5    所有 OSPF 的路由器

224.0.0.6    OSPF 指派路由器

224.0.0.9    RPIv2 路由器

224.0.0.10  EIGRP 路由器

224.0.0.13  PIM 路由器

224.0.0.22  IGMPv3

224.0.0.25  RGMP

224.0.1.1    NTP 网络时间

三、多播地址与 MAC 地址的映射

使用同一个 IP 多播地址接收多播数据包的所有主机构成了一个主机组,也称为多播组。一个多播组的成员是随时变动的,一台主机可以随时加入或离开多播组,多播组成员的数目和所在的地理位置也不受限制,一台主机也可以属于几个多播组。

这个我们可以这样理解,多播地址就类似于 QQ 群号,多播组相当于 QQ 群,一个个的主机就相当于群里面的成员

 IPv4 的 D 类地址是多播地址。IEEE 把一块以太网多播组地址分给 IANA 以支持IP多播。块的地址都以 01:00:5e 开头,第 25 位为 0,低 23 位为 IPv4 多播地址( D类地址 )的低 23 位。IPv4 多播地址与 MAC 地址的映射关系如图所示:

由于多播地址( D类地址 )中的最高 5bit 在映射过程中被忽略,因此每个以太网多播地址对应的多播组是不唯一的。32 个不同的多播组号被映射为一个以太网地址。例如,多播地址 224.128.64.32(十六进制 e0.80.40.20)和 224.0.64.32(十六进制 e0.00.40.20)都映射为同一以太网地址 01:00:5e:00:40:20。

既然地址映射是不唯一的,那么设备驱动程序或 IP 层就必须对数据报进行过滤。因为网卡可能接收到主机不想接收的多播数据帧,如下图,假如主机 1 加入的多播为 224.128.64.32, 主机 2 加入的多播为 224.0.64.32,我们想给 224.0.64.32 所在的多播组 ( 主机 2 ) 发送信息,数据经过网卡时,224.128.64.32 (主机 1 ) 和 224.0.64.32 (主机 2 ) 所在多播组的网卡都会收到数据,因为它们的 MAC 地址都是 01:00:5e:00:40:20。这时候,如果网卡不提供足够的多播数据帧过滤功能,设备驱动程序就必须接收所有多播数据帧,然后对它们进行

四、套接口选项

int setsockopt( int sockfd, int level,int optname,

const void *optval, socklen_t optlen );

成功执行返回0,否则返回-1

1)选项 IP_MULTICAST_LOOP

默认情况下,当本机发送组播数据到某个网络接口时,在 IP 层,数据会回送到本地的回环接口,选项 IP_MULTICAST_LOOP 用于控制数据是否回送到本地的回环接口。

例如:

unsigned int loop = 1;

// 参数 loop 设置为 0 禁止回送,设置为 1 允许回送。

setsockopt(sockfd, IPPROTO_IP,

IP_MULTICAST_LOOP, &loop, sizeof(loop));

2)选项 IP_ADD_MEMBERSHIP 和 IP_DROP_MEMBERSHIP

加入或者退出一个多播组,通过选项 IP_ADD_MEMBERSHIP 和 IP_DROP_MEMBERSHIP,对一个结构 struct ip_mreq 类型的变量进行控制,struct ip_mreq 原型如下:

struct in_addr

{

in_addr_t s_addr;

}

struct ip_mreq

{

struct in_addr imn_multiaddr; // 多播组 IP,类似于 QQ 群号

struct in_addr imr_interface;   // 将要添加到多播组的 IP,类似于QQ 成员号

};

多播只能用 UDP 或原始 IP 实现,不能用 TCP。

加入多播实例:

[objc] view plaincopy
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #include <sys/types.h>
  11. int main(int argc, char*argv[])
  12. {
  13. int sockfd; // 套接字文件描述符
  14. struct sockaddr_in local_addr; // 本地地址
  15. int err = -1;
  16. char group[16] = "224.0.0.88"; // 多播组 IP
  17. sockfd = socket(AF_INET, SOCK_DGRAM, 0);  //建立套接字
  18. if (sockfd == -1)
  19. {
  20. perror("socket()");
  21. return -1;
  22. }
  23. // 初始化地址
  24. memset(&local_addr, 0, sizeof(local_addr));
  25. local_addr.sin_family = AF_INET;
  26. local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  27. local_addr.sin_port = htons(8000);
  28. // 绑定socket
  29. err = bind(sockfd,(struct sockaddr*)&local_addr, sizeof(local_addr));
  30. if(err < 0)
  31. {
  32. perror("bind()");
  33. return -2;
  34. }
  35. // 设置回环许可,控制数据允许回送到本地的回环接口
  36. int loop = 1;
  37. err = setsockopt(sockfd,IPPROTO_IP, IP_MULTICAST_LOOP,&loop, sizeof(loop));
  38. if(err < 0)
  39. {
  40. perror("setsockopt():IP_MULTICAST_LOOP");
  41. return -3;
  42. }
  43. struct ip_mreq mreq; // 多播地址结构体
  44. // 加入多播组,相当于创建一个QQ群,某人加入此群
  45. mreq.imr_multiaddr.s_addr = inet_addr(group); // 多播地址,类似于 QQ 群号
  46. mreq.imr_interface.s_addr = htonl(INADDR_ANY);// 将本机加入多播组,类似于某人加入此群
  47. // 加入多播组
  48. err = setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq, sizeof(mreq));
  49. if (err < 0)
  50. {
  51. perror("setsockopt():IP_ADD_MEMBERSHIP");
  52. return -4;
  53. }
  54. int times = 0;
  55. int addr_len = 0;
  56. char buff[256] = {0};
  57. int n = 0;
  58. // 循环接收广播组的消息,5次后退出
  59. for(times = 0; times<5; times++)
  60. {
  61. addr_len = sizeof(local_addr);
  62. memset(buff, 0, sizeof(buff));
  63. // 接收数据
  64. n = recvfrom(sockfd, buff, sizeof(buff), 0,(struct sockaddr*)&local_addr, &addr_len);
  65. if( n== -1)
  66. {
  67. perror("recvfrom()");
  68. }
  69. printf("Recv %dst message from server:%s\n", times, buff);
  70. sleep(2);
  71. }
  72. // 退出广播组
  73. err = setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,&mreq, sizeof(mreq));
  74. close(sockfd);
  75. return 0;
  76. }


向多播组发送信息的测试示例:

[objc] view plaincopy
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #include <sys/types.h>
  11. int main(int argc, char*argv)
  12. {
  13. int sockfd; // 套接字文件描述符
  14. struct sockaddr_in dest_addr; // 目标ip
  15. char buf[] = "BROADCAST TEST DATA";
  16. sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 建立套接字
  17. if (s == -1)
  18. {
  19. perror("socket()");
  20. return -1;
  21. }
  22. // 初始化目标 ip 信息
  23. memset(&dest_addr, 0, sizeof(dest_addr));
  24. dest_addr.sin_family = AF_INET;
  25. dest_addr.sin_addr.s_addr = inet_addr("224.0.0.88"); // 目的地址,为多播地址
  26. dest_addr.sin_port = htons(8000);   // 多播服务器的端口也是 8000
  27. // 向多播地址发送数据
  28. while(1){
  29. int n = sendto(sockfd, buf, strlen(buf), 0,(struct sockaddr*)&dest_addr, sizeof(dest_addr));
  30. if( n < 0)
  31. {
  32. perror("sendto()");
  33. return -2;
  34. }
  35. sleep(1);
  36. }
  37. return 0;
  38. }

Linux网络编程——多播相关推荐

  1. 【Linux网络编程】组播

    00. 目录 文章目录 00. 目录 01. 组播概述 02. 组播应用分类 03. 组播地址 04. 组播地址与 MAC 地址的关系 05. 套接字选项 06. 程序示例 07. 附录 01. 组播 ...

  2. 【Linux网络编程】广播

    00. 目录 文章目录 00. 目录 01. 广播概述 02. 广播地址分类 03. 广播的特点 04. setsockopt函数 05. 程序示例 06. 附录 01. 广播概述 在生活中广播无处不 ...

  3. Linux网络编程——千峰物联网笔记

    B站视频:千峰物联网学科linux网络编程 网址:https://www.bilibili.com/video/BV1RJ411B761?p=1 目录 第一章:计算机网络概述 1.1计算机网络发展简史 ...

  4. 【Linux网络编程】UDP 套接字编程

    [Linux网络编程]UDP 套接字编程 [1]用户数据报协议(UDP) UDP是一个简单的传输层协议,不保证UDP数据报会到达其最终目的地,不保证各个数据报的先后顺序跨网络后保持不变,也不保证每个数 ...

  5. linux网络编程 ppt,LINUX网络编程.ppt

    <LINUX网络编程.ppt>由会员分享,可在线阅读,更多相关<LINUX网络编程.ppt(47页珍藏版)>请在人人文库网上搜索. 1.LINUX网络编程,行业事业部 黄文举 ...

  6. 很全的linux网络编程技巧

    注:作者王晓,本人认为总结得很好,故记之,绝无侵权之意. 本文转自:https://www.cnblogs.com/jfyl1573/p/6476607.html 看到好文章想留做自己学习,如有侵权, ...

  7. Linux网络编程-很全面

    注:作者王晓,本人认为总结得很好,故记之,绝无侵权之意. 1. LINUX网络编程基础知识 1 1.1. TCP/IP协议概述 1 1.2. OSI参考模型及TCP/IP参考模型 1 1.3. TCP ...

  8. linux网络编程-很全的

    注:作者王晓,本人认为总结得很好,故记之,绝无侵权之意. 1. LINUX网络编程基础知识 1 1.1. TCP/IP协议概述 1 1.2. OSI参考模型及TCP/IP参考模型 1 1.3. TCP ...

  9. 【Linux网络编程】

    文章目录 一. Linux的网络模型 1. 网络模型概述 2. Linux网络协议栈包含的网络协议 3. Linux网络编程模型 4. socket套接字编程模型 二. UDP编程 1 编程准备-字节 ...

  10. Linux网络编程--进程间通信(一)

    进程间通信简介(摘自<Linux网络编程>p85) AT&T 在 UNIX System V 中引入了几种新的进程通讯方式,即消息队列( MessageQueues),信号量( s ...

最新文章

  1. 【干货】百度联合清华大学发布国内首个基于AI实践的《产业智能化白皮书》(附报告全文)...
  2. LeetCode-剑指 Offer 25. 合并两个排序的链表
  3. PHP中的预定义常量
  4. java reactor框架_Java反应式框架Reactor中的Mono和Flux
  5. python自然语言处理评论_python自然语言处理——学习笔记:Chapter3纠错
  6. 关于 命令行参数 main(int argc,char** argv)
  7. Python数据分析学习笔记:使用SciKit-Learn进行数据规范化
  8. 敏捷 - #2 原则:欢迎更改要求 ( #2 Agile - Principle)
  9. 第五讲 交错级数、绝对收敛和条件收敛
  10. 记一次串口调试工具发指令无反应问题
  11. linux将文件修改时间改为现在
  12. 最新外卖霸王餐系统程序源码|美团/饿了么霸王餐系统(含数据库)(可对接公众号)
  13. 【Python】面试官:元组列表都分不清,回去等通知pa
  14. “整合”还是“混合”——多因子组合的构建
  15. C语言计算程序运行时间简单实例
  16. 【Kotlin 初学者】字符串常用操作汇总
  17. postgresql修改密码
  18. LIMS实验室系统管理软件的国内外应用现状
  19. 闲话乱侃——26字母软件开发语言命名是否用完了?
  20. 择时策略1:一个金叉死叉(python)

热门文章

  1. Android CheckBox 实战
  2. Sqoop Java API 导入应用案例
  3. 6.字符串截取数据求平均分
  4. 2015年下半年的读书技术
  5. traceroute tracert
  6. 个人.NET ORM全攻略,提供最新版本下载
  7. 被监控机上安装nagios插件和nrpe(nrpe添加为xinetd服务)
  8. 不同VLAN间的通信
  9. 游戏开发之深拷贝与浅拷贝(C++基础)
  10. 华为STP相关功能配置