【miscellaneous】IP多播技术及其编程
发信站: 幽幽黄桷兰 (Mon Jun 16 10:35:39 2003)
转信站: SMTH!maily.cic.tsinghua.edu.cn!news2.uestc.edu.cn!CQUPT
IP多播(也称多址广播或组播)技术,是一种允许一台或多台主机(多播源)发送单一
数据包到多台主机(一次的,同时的)的TCP/IP网络技术。多播作为一点对多点的通信
,是节省网络带宽的有效方法之一。在网络音频/视频广播的应用中,当需要将一个节点
的信号传送到多个节点时,无论是采用重复点对点通信方式,还是采用广播方式,都会
严重浪费网络带宽,只有多播才是最好的选择。多播能使一个或多个多播源只把数据包
发送给特定的多播组,而只有加入该多播组的主机才能接收到数据包。目前,IP多播技
术被广泛应用在网络音频/视频广播、AOD/VOD、网络视频会议、多媒体远程教育、“pu
sh”技术(如股票行情等)和虚拟现实游戏等方面。
一、IP多播技术简介
1.IP多播地址和多播组
IP多播通信必须依赖于IP多播地址,在IPv4中它是一个D类IP地址,范围从224.0.0.0到
239.255.255.255,并被划分为局部链接多播地址、预留多播地址和管理权限多播地址三
类。其中,局部链接多播地址范围在224.0.0.0~224.0.0.255,这是为路由协议和其它用
途保留的地址,路由器并不转发属于此范围的IP包;预留多播地址为224.0.1.0~238.25
5.255.255,可用于全球范围(如Internet)或网络协议;管理权限多播地址为239.0.0
.0~239.255.255.255,可供组织内部使用,类似于私有IP地址,不能用于Internet,可
限制多播范围。
使用同一个IP多播地址接收多播数据包的所有主机构成了一个主机组,也称为多播组。
一个多播组的成员是随时变动的,一台主机可以随时加入或离开多播组,多播组成员的
数目和所在的地理位置也不受限制,一台主机也可以属于几个多播组。此外,不属于某
一个多播组的主机也可以向该多播组发送数据包。
2.IP多播技术的硬件支持
要实现IP多播通信,要求介于多播源和接收者之间的路由器、集线器、交换机以及主机
均需支持IP多播。目前,IP多播技术已得到硬件、软件厂商的广泛支持。
(1)主机
支持IP多播通信的平台包括Windows CE 2.1、Windows 95、Windows 98、Windows NT 4
和Windows 2000等,运行这些操作系统的主机都可以进行IP多播通信。此外,新生产的
网卡也几乎都提供了对IP多播的支持。
(2)集线器和交换机
目前大多数集线器、交换机只是简单地把多播数据当成广播来发送接收,但一些中、高
档交换机提供了对IP多播的支持。例如,在3COM SuperStack 3 Swith 3300交换机上可
启用802.1p或IGMP多播过滤功能,只为已侦测到IGMP数据包的端口转发多播数据包。
(3)路由器
多播通信要求多播源节点和目的节点之间的所有路由器必须提供对Internet组管理协议
(IGMP)、多播路由协议(如PIM、DVMRP等)的支持。
当一台主机欲加入某个多播组时,会发出“主机成员报告”的IGMP消息通知多播路由器
。当多播路由器接收到发给那个多播组的数据时,便会将其转发给所有的多播主机。多
播路由器还会周期性地发出“主机成员查询”的IGMP消息,向子网查询多播主机,若发
现某个多播组已没有任何成员,则停止转发该多播组的数据。此外,当支持IGMP v2的主
机(如Windows 98/2000计算机)退出某个多播组时,还会向路由器发送一条“离开组
”的IGMP消息,以通知路由器停止转发该多播组的数据。但只有当子网上所有主机都退
出某个多播组时,路由器才会停止向该子网转发该多播组的数据。
使用多播路由协议,路由器可建立起从多播源节点到所有目的节点的多播路由表,从而
实现在子网间转发多播数据包。例如,PIM(协议独立多播)就是一种多播路由协议,它
有两种类型:稀疏模式(sparse-mode)和密集模式(dense-mode)。以Cisco 2621路由
器为例,启用IP多播转发功能的基本设置如下:
c2621(config)# ip multicast-routing 启动IP多播,使路由器成为一个多播路由器
c2621(config)# int f0/0 配置快速以太网端口0
c2621(config-if)# ip pim dense-mode(或sparse-mode)启动PIM,同时激活IGMP协议
c2621(config-if)# int f0/1 配置快速以太网端口1
c2621(config-if)# ip pim dense-mode(或sparse-mode)
二、IP多播应用的编程方法
在实际应用中,编程人员通常需要自己编制底层网络应用程序来实现网上的底层通信,
如具体实现IP多播通信的功能。编制底层网络应用程序通常要借助于网络数据通信编程
接口,而在不同的操作系统中所提供的网络编程接口是有所不同的,如在Microsoft Wi
ndows环境下的网络编程接口就是Windows套接字(Windows Socket,简称Winsock)。
Winsock提供了包括TCP/IP、IPX等多种通信协议下的编程接口。不同的Windows版本支持
不同的Winsock版本,其中Windows 95等早期版本本身只支持Winsock1.1(16位)下的编
程(可以通过安装相关的软件包使其支持Winsock2.0),而Windows98、Windows NT4.0
、Windows 2000则直接支持Winsock2.0(32位)。Winsock2.0是Winsock1.1的扩展,除
兼容Winsock1.1 API外,还定义了一套可支持IP多播的与协议无关的API。
使用Winsock 2.0实现IP多播的一般步骤如下:
1.初始化Winsock资源
在使用Winsock之前,必须调用WSAStartup()函数初始化Windows Sockets DLL。它允许
应用程序或DLL指定Windows Sockets API要求的版本。
2.创建套接字
调用WSASocket()函数可以创建一个使用UDP协议的套接字,它是加入多播组的初始化套
接字,并且以后数据的发送和接收都在该套接字上进行。针对IP多播通信,可将参数dw
Flags设置为WSA_FLAG_MULTIPOINT_C_LEAF、WSA_FLAG_MULTIPOINT_D_LEAF和WSA_FLAG_
OVERLAPPED的位和,指明IP多播通信在控制层面和数据层面都是“无根的”,只存在叶
节点,它们可以任意加入一个多播组,而且从一个叶节点发送的数据会传送到每一个叶
节点(包括它自己);创建的套接字具有重叠属性。
3.设置套接字的选项
调用setsockopt()函数为套接字设置SO_REUSEADDR选项,以允许套接字绑扎到一个已在
使用的地址上。
4.绑定套接字
调用bind()函数绑定套接字,从而将创建好的套接字与本地地址和本地端口联系起来。
对于多播通信来说,发送和接收数据通常采用同一个端口。
5.设置多播套接字的模式
WSAIoctl()函数的命令码SIO_MULTICAST_LOOP用来允许或禁止多播通信时发送出去的通
信流量是否也能够在同一个套接字上被接收(即多播返回)。值得注意的是,在Window
s 95/98/NT 4中,默认是允许多播返回,但不能设置禁止,否则会出错;只有在Window
s 2000以上版本中,才能设置允许/禁止多播返回。
WSAIoctl()函数的命令码SIO_MULTICAST_SCOPE用来设置多播传播的范围,即生存时间T
TL。每当多播路由器转发多播数据包时,数据包中的TTL值都会被减1,若数据包的TTL减
少到0,则路由器将抛弃该数据包。TTL的值是多少,多播数据便最多能经过多少个多播
路由器。例如,TTL值为0,则多播只能在本地主机的多个套接字间传播,而不能传播到
“网线”上;TTL值为1(默认值),则多播数据遇到第一个路由器,便会被它“无情”
地丢弃,不允许传出本地网络之外,即只有同一个网络内的多播组成员才能收到多播数
据。
6.加入一个多播组
调用WSAJoinLeaf()函数可加入一个多播组并指定角色(发送者/接收者)。调用时,参
数dwFlags可指定套接字作为发送者(JL_SENDER_ONLY)、接收者(JL_RECEIVER_ONLY)
或身兼两者(JL_BOTH)。调用成功后会返回一个多播套接字,调用closesocket()函数
关闭该套接字就离开了多播组,此时可以调用WSAJoinLeaf()函数再次加入多播组。注意
,对多播组数据的接收和发送不能在该套接字上完成。
7.向多播组发送数据
调用sendto()函数,可在指定的UDP套接字上向指定的多播组发送多播数据。调用时,参
数to应指向多播组的IP地址。值得注意的是,若一个应用程序只是打算给多播组发送数
据,便不必加入一个多播组。
8.等待事件
调用WSAAsyncSelect()函数,使套接字置于非阻塞模式,这时应用程序就可在该套接字
上接收以Windows消息为基础的网络事件通知。例如,若参数lEvent值为FD_READ,则应
用程序可在套接字上接收到“数据正等待被读入”的通知。
9.从多播组接收数据
调用recvfrom函数,可在指定的UDP套接字上读取输入数据。多播通信中数据的发送与接
收一般采用同一个端口,因此其发送套接字和接收套接字是一样的。
10.关闭套接字,释放Winsock资源。
在多播通信结束后,先调用closesocket()函数关闭多播套接字和UDP套接字,然后调用
WSACleanup()函数结束对Windows Sockets DLL的使用。
三、应用实例
为了说明IP多播技术的应用方法,本人在Visual C++.NET环境下设计了一个简单的基于
Windows Socket 2的IP多播应用程序,通过该例子读者可以掌握IP多播应用程序设计的
一般方法。该程序的具体设计方法如下:
1.在Visual Studio.NET中建立一个基于对话框的MFC项目CMulticastSocket。注意在“
高级功能”设置中不要选择“Windows套接字”,这是因为MFC只支持Windows Socket 1
而不支持Windows Socket 2。为了能使用Winsock 2 API编程,在程序中应包含“winso
ck2.h”头文件,并在项目中加入ws2_32.lib的静态库,该静态库应设置在项目属性的“
链接器”\“输入”\“附加依赖项”中。
2.在对话框(类名CCMulticastSocketDlg)资源中,设置它的Caption为“WinSock 2多
播应用程序”,并添加以下控件:
静态文本:Caption为“接收到的信息:”;
编辑框:ID为IDC_RECEIVE_EDIT,Read Only、Auto Vscroll、Vertical Scroll和Mult
iline属性值都为True
静态文本:Caption为“发送的信息:”
编辑框:ID为IDC_SEND_EDIT
第一个按钮:Caption为“加入多播组(&J)”,ID为IDC_JOIN_BUTTON
第二个按钮:Caption为“多播发送(&S)”,ID为IDC_SEND_BUTTON
第三个按钮:Caption为“离开多播组(&L)”,ID为IDC_LEAVE_BUTTON
第四个按钮:Caption为“退出(&Q)”,ID为IDC_QUIT_BUTTON
为两个编辑框分别添加相关联的CString类型的变量m_SendMessage和m_ReceiveMessage
;为四个按钮添加相应的消息处理函数;为对话框添加定时器消息(用于定时显示接收
到的消息)及其消息处理函数。
3.添加一个新的对话框资源,设置它的Caption为“加入多播组”,保留默认的两个按
钮控件,同时添加添加以下控件:
静态文本:Caption为“IP多播组地址:”
编辑框:ID为IDC_IPADDRESS_EDIT
静态文本:Caption为“IP多播端口:”
编辑框:ID为IDC_PORT_EDIT
静态文本:Caption为“生存时间:”
编辑框:ID为IDC_TTL_EDIT
复选框:Caption为“多播返回:”,ID为IDC_LOOPBACK_CHECK,Left Text属性值为Tr
ue。
为该对话框添加新的类CJoinGroupDlg,它的基类为CDialog,然后为该对话框中的三个
编辑框分别添加相关联的变量,即CSting m_IPAddress、UINT m_nPort、UINT m_nTTL;
为复选框添加相关联的BOOL类型的变量m_Loopback。
4.在CMulticastSocketDlg.h文件的前面添加CJoinGroupDlg的头文件:#include “Jo
inGroupDlg.h”,并在CCMulticastSocketDlg类中添加了一个CJoinGroupDlg类实例对象
m_JoinDlg。
5.为了能在对话框中接收网络事件通知,应增加一个用户自定义的消息及消息处理函数
,具体实现方法如下:在CMulticastSocketDlg.h文件的前面自定义消息:#define WM_
SOCK_MSG(WM_USER+166),并在afx_msg块中说明消息处理函数:afx_msg LRESULT OnSo
cketMsg (WPARAM wParam,LPARAM lParam);在CMulticastSocketDlg.cpp文件中的消息
映射块中,使用ON_MESSAGE (WM_SOCK_MSG,OnSocketMsg)宏指令将消息映射到消息处理
函数中,并具体实现消息处理函数:LRESULT CCMulticastSocketDlg:: OnSocketMsg(W
PARAM wParam,LPARAM lParam){…}。
该程序的主要代码可参见程序清单,相关函数的详细说明可参看Microsoft MSDN帮助系
统。为了节省篇幅,程序中省略了部分自动生成的和用于错误处理的代码。
程序清单:
// CMulticastSocketDlg.cpp : 实现文件
#include "stdafx.h"
#include "winsock2.h"
#include "CMulticastSocket.h"
#include "CMulticastSocketDlg.h"
……
DWORD cbRet;
SOCKET Sock,SockM; //UDP套接字,多播套接字
BOOL bFlag,bJoin;
SOCKADDR_IN local,Remote,From; //分别指向本地、多播组和数据来源的IP地址与端口
int Fromlen;
char ReceiveBuf[32000]; //接收缓冲区
BOOL bDataReceived;
……
BEGIN_MESSAGE_MAP(CCMulticastSocketDlg, CDialog)
……
ON_BN_CLICKED(IDC_JOIN_BUTTON, OnBnClickedJoinButton)
ON_BN_CLICKED(IDC_LEAVE_BUTTON, OnBnClickedLeaveButton)
ON_BN_CLICKED(IDC_QUIT_BUTTON, OnBnClickedQuitButton)
ON_BN_CLICKED(IDC_SEND_BUTTON, OnBnClickedSendButton)
ON_WM_TIMER()
ON_MESSAGE(WM_SOCK_MSG,OnSocketMsg)
END_MESSAGE_MAP()
BOOL CCMulticastSocketDlg::OnInitDialog()
{
CDialog::OnInitDialog();
……
SetTimer(1,100,NULL); //设置定时器
Fromlen=sizeof(From);
bDataReceived=TRUE;
bJoin=FALSE;
return TRUE; // 除非设置了控件的焦点,否则返回 TRUE
}
……
void CCMulticastSocketDlg::OnBnClickedJoinButton() //加入多播组
{
if(m_JoinDlg.DoModal()==IDOK)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2,2);
err = WSAStartup(wVersionRequested, &wsaData); //初始化WinSock2资源
if(err!= 0){
AfxMessageBox("不能加载Windows套接字动态链接库,MB_OK");
return;
}
if (LOBYTE(wsaData.wVersion) !=2 || HIBYTE(wsaData.wVersion) !=2){
AfxMessageBox("WinSock DLL不支持2.0版本,MB_OK");
WSACleanup( );
return;
}
//创建一个套接字
Sock=WSASocket(AF_INET,SOCK_DGRAM,IPPROTO_UDP,
(LPWSAPROTOCOL_INFO)NULL,0,WSA_FLAG_OVERLAPPED
| WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF);
bFlag=TRUE; //设置套接字选项,使套接字为可重用端口地址
setsockopt(Sock,SOL_SOCKET,SO_REUSEADDR,(char*)&bFlag,sizeof(bFlag));
//将套接字绑定到用户指定端口及默认的接口
memset(&local,0,sizeof(local));
local.sin_family=AF_INET;
local.sin_port=htons((USHORT)m_JoinDlg.m_nPort);
local.sin_addr.s_addr=htonl(INADDR_ANY);
bind(Sock,(struct sockaddr FAR *)&local,sizeof(local));
//设置多播数据报传播范围(生存时间TTL)
WSAIoctl(Sock,SIO_MULTICAST_SCOPE,&m_JoinDlg.m_nTTL,sizeof(int),
NULL,0,&cbRet,NULL,NULL);
//设置多播返回(LOOKBACK)
BOOL nLoopBack=m_JoinDlg.m_Loopback;
WSAIoctl(Sock,SIO_MULTIPOINT_LOOPBACK,&nLoopBack,sizeof(nLoopBack),
NULL,0,&cbRet,NULL,NULL);
memset(&Remote,0,sizeof(Remote));
Remote.sin_family=AF_INET;
Remote.sin_addr.s_addr=inet_addr(m_JoinDlg.m_IPAddress);
Remote.sin_port=htons(m_JoinDlg.m_nPort);
//加入到指定的多播组,并指定为既作为发送者又作为接收者(JL_BOTH)
SockM=WSAJoinLeaf(Sock,(sockaddr*)&Remote,sizeof(Remote),
NULL,NULL,NULL,NULL,JL_BOTH);
WSAAsyncSelect(Sock,m_hWnd,WM_SOCK_MSG,FD_READ); //注册网络消息及其网络事件
bJoin=TRUE;
}
}
void CCMulticastSocketDlg::OnBnClickedSendButton() //多播发送
{
if(bJoin){
UpdateData(TRUE);
const char* strMessage=LPCTSTR(m_SendMessage);
int nSize=m_SendMessage.GetLength()+1;
sendto(Sock,strMessage,nSize,0,(sockaddr*)&Remote,sizeof(Remote));
}
else
AfxMessageBox("请先加入多播组!");
m_SendMessage="";
UpdateData(FALSE);
}
void CCMulticastSocketDlg::OnBnClickedLeaveButton()
{ //离开多播组
closesocket(SockM);
closesocket(Sock);
WSACleanup();
m_SendMessage="";
m_ReceiveMessage="";
bDataReceived=TRUE;
bJoin=FALSE;
UpdateData(FALSE);
}
void CCMulticastSocketDlg::OnBnClickedQuitButton()
{ //退出
DestroyWindow();
}
void CCMulticastSocketDlg::OnTimer(UINT nIDEvent) //定时器处理函数,实现接收
信息的定时更新
{
if(bDataReceived)
{
m_ReceiveMessage+=ReceiveBuf;
m_ReceiveMessage+="\r\n";
bDataReceived=FALSE;
UpdateData(FALSE);
}
CDialog::OnTimer(nIDEvent);
}
LRESULT CCMulticastSocketDlg::OnSocketMsg(WPARAM wParam,LPARAM lParam)
{
//检索网络事件
switch(WSAGETSELECTEVENT(lParam)){
case FD_READ:
recvfrom(Sock,ReceiveBuf,32000,0,(sockaddr *)&From,&Fromlen);
bDataReceived=TRUE; //设置已接收到一条信息标志
break;
}
return TRUE;
}
转载于:https://www.cnblogs.com/huty/p/8517725.html
【miscellaneous】IP多播技术及其编程相关推荐
- IP多播技术[为软件高校杯做准备]
转眼10月份将至,今年的高校杯应该轮到我参加了吧..得准备一下先.开发课题已经选好 << 多媒体远程教育>>,开发语言:C# 模式:C/S 基与WinForm. 其中涉及到 ...
- IP多播技术及其应用
随着全球互联网(Internet)的迅猛发展,上网人数正以几何级数快速增长,以因特网技术为主导的数据通信在通信业务总量中的比列迅速上升,因特网业务已成为多媒体通信业中发展最为迅速.竞争最为激烈的领域. ...
- IP多播技术介绍(二)
2.MOSPF(Multicast OSPF) 开放式组播最短路径优先(MOSPF)由FRC1584为OSPF组播的扩展,是OSPFV2单播路由协议的一个扩展. 组播扩展 OSPF(MOSPF)在原 ...
- 管理active directiory中的用户和计算机管理磁盘,IP多播桌面视频会议系统媒体流管理与安全机制的分析.pdf...
摘要 摘 要 近年来,随着网络技术的发展和通信技术的进步,人与人的交流日趋频繁. 由此视频会议系统已成为研究的一个热点.本文介绍了利用cOM组件技术开发的 一套基于IP多播的讨论式桌面会议系统,并且介 ...
- 基于C++的Qt网络编程——基于 IP 多播的网络会议程序
目录 一.实验题目 二.实验目的 三.总体设计 1.实验原理 2.设计步骤 四.详细设计 1.程序流程图 2.实验代码(部分) 五.实验结果与分析 六.小结与心得体会 一.实验题目 基于 IP 多播的 ...
- 网络编程之---广播和IP多播
一.广播 1.接收 void main() {SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0);// 首先要绑定一个本地地址,指明广播端口号SOCKADDR_IN ...
- 视频教程-思科CCNP专题系列13:IP多播协议-思科认证
思科CCNP专题系列13:IP多播协议 新任帮主,双CCIE(CCIE R&S,CCIE Security):2011年前在国内知名培训机构担任CCIE R&S讲师:因一直秉持知行统一 ...
- 《IP多播网络的设计与部署(第1卷)》——2.1 多播地址
本节书摘来异步社区<IP多播网络的设计与部署(第1卷)>一书中的第2章,第2.1节,作者:[美]Beau Williamson,更多章节内容可以访问云栖社区"异步社区" ...
- 计算机网络(十九)其他IP相关技术
计算机网络(十九)其他IP相关技术 1.IP多播相关技术 2.IP任播 3.通信质量控制 a.控制通信质量的机制 b.IntServ c.DiffServ 4.显式拥塞通知 5.Mobile IP a ...
最新文章
- 七喜携手AMD,摆脱英特尔“潜规则”
- java 集合读写同步_JAVA多线程学习十六 - 同步集合类的应用
- pyqt5 自定义控件_PyQt5学习笔记(十六)Pyinstaller打包与SQLite数据库
- 寺庙的纪律性也让我颇有感触
- [转载] 语言程序设计第4版黄洪艺_计算机二级教程 Python语言程序设计 第8章python计算生态...
- 人工智能学习(二)安装tensorflow与pytorch
- [2019杭电多校第四场][hdu6614]AND Minimum Spanning Tree(贪心)
- molloc/free和new/delete的区别
- 如何安装PDF打印机
- 记一次有惊无险的 JVM 优化经历
- 【张朝阳的物理课笔记】 1. 力,牛顿定律,飞船角速度
- nginx+uWSGI+django+virtualenv+supervisor发布web服务器流程
- 前端实战:教你写出简单的侧边栏功能以及返回顶部特效
- JS原生实现照片抽奖
- 某cpws - ciphertext加密与数据解密
- 第七章集合与字典作业
- 机房管理系列之电话交换机
- codeup刷题2.5小节 C/C++快速入门->数组——《算法笔记》(胡凡)
- 模仿京东tab切换--自创
- 查询服务器硬盘上电时间,鲁大师检测硬盘通电时间怎么操作?检测硬盘通电时间教程...
热门文章
- 4个不同小球放入4个不同盒子_初婚老公和二婚老公有什么不同?听听这4个再婚女人的真实想法...
- python3字符串操作_python3-字符串操作
- 【maven】mvn -pl 指定模块
- linux 修改ssh banner
- c语言中从键盘上输入三个数,将之排序后按由大到小的顺序输出,从键盘上输入3个数,将它们按由大到小的顺序排列好输出...
- aws s3 php,Amazon S3 预签名 POSTs 与 AWS SDK for PHP 版本 3 - 适用于 PHP 的 AWS 开发工具包...
- power系列服务器问题品管主任,了解 Power BI 管理员角色
- oracle的catalog,Oracle Rman Catalog的创建方法和备份原理
- 四象限运行模式_信息流广告推广怎么选择正确的出价模式?
- onlyoffice 收费不_西班牙银行开始泛滥收费,柜面取钱也要手续费