• IP多播技术知识、应用及其编程技术


    随着全球互联网(Internet)的迅猛发展,上网人数正以几何级数快速增长,以因特网技术为主导的数据通信在通信业务总量中的比列迅速上升,因特网业务已成为多媒体通信业中发展最为迅速、竞争最为激烈的领域。Internet网络传输和处理能力的大幅提高,使得网上应用业务越来越多,特别是视音频压缩技术的发展和成熟,使得网上视音频业务成为Internet网上最重要的业务之一。

    在Internet上实现的视频点播(VOD)、可视电话、视频会议等视音频业务和一般业务相比,有着数据量大、时延敏感性强、持续时间长等特点。因此采用最少时间、最小空间来传输和解决视音频业务所要求的网络利用率高、传输速度快、实时性强的问题,就要采用不同于传统单播、广播机制的转发技术及QoS服务保证机制来实现,而IP多播技术是解决这些问题的关键技术。

    一、IP多播技术的概念

    IP多播(也称多址广播或组播)技术,是一种允许一台或多台主机(多播源)发送单一数据包到多台主机(一次的,同时的)的TCP/IP网络技术。多播作为一点对多点的通信,是节省网络带宽的有效方法之一。在网络音频/视频广播的应用中,当需要将一个节点的信号传送到多个节点时,无论是采用重复点对点通信方式,还是采用广播方式,都会严重浪费网络带宽,只有多播才是最好的选择。多播能使一个或多个多播源只把数据包发送给特定的多播组,而只有加入该多播组的主机才能接收到数据包。目前,IP多播技术被广泛应用在网络音频/视频广播、AOD/VOD、网络视频会议、多媒体远程教育、“push”技术(如股票行情等)和虚拟现实游戏等方面。

    二、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.255.255.255,可用于全球范围(如Internet)或网络协议;管理权限多播地址为239.0.0.0~239.255.255.255,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制多播范围。

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

    2.多播分布树

    为了向所有接收主机传送多播数据,用多播分布树来描述IP多播在网络中传输的路径。多播分布树有两个基本类型:有源树和共享树。

    有源树是以多播源作为有源树的根,有源树的分支形成通过网络到达接收主机的分布树,因为有源树以最短的路径贯穿网络,所以也常称为最短路径树(SPT)。共享树以多播网中某些可选择的多播路由中的一个作为共享树的公共根,这个根被称为汇合点(RP)。共享树又可分为单向共享树和双向共享树。单向共享树指多播数据流必须经过共享树从根发送到多播接收机。双向共享树指多播数据流可以不经过共享树。

    3.逆向路径转发

    逆向路径转发(RPF)是多播路由协议中多播数据转发过程的基础,其工作机制是当多播信息通过有源树时,多播路由器检查到达的多播数据包的多播源地址,以确定该多播数据包所经过的接口是否在有源的分支上,如果在,则RPF检查成功,多播数据包被转发;如果RPF检查失败,则丢弃该多播数据包。

    4.Internet多播主干(MBONE)网络

    Internet多播主干(MBONE)网络是由一系列相互连接的子网主机和相互连接支持IP多播的路由器组成。它可以看成是一个架构在Internet物理网络上层的虚拟网,在该虚拟网中,多播源发出的多播信息流可直接在支持IP多播的路由器组之间传输,而在多播路由器组和非多播路由器组之间要通过点对点隧道技术进行传输。
     

    三、IP多播路由及其协议

    1. IP多播路由的基本类型

    多播路由的一种常见的思路就是在多播组成员之间构造一棵扩展分布树。在一个特定的“发送源,目的组”对上的IP多播流量都是通过这个扩展树从发送源传输到接受者的,这个扩展树连接了该多播组中所有主机。不同的IP多播路由协议使用不同的技术来构造这些多播扩展树,一旦这个树构造完成,所有的多播流量都将通过它来传播。

    根据网络中多播组成员的分布,总的说来IP多播路由协议可以分为以下两种基本类型。第一种假设多播组成员密集地分布在网络中,也就是说,网络大多数的子网都至少包含一个多播组成员,而且网络带宽足够大,这种被称作“密集模式”(Dense-Mode)的多播路由协议依赖于广播技术来将数据“推”向网络中所有的路由器。密集模式路由协议包括距离向量多播路由协议(DVMRP:Distance Vector Multicast Routing Protocol)、多播开放最短路径优先协议(MOSPF:Multicast Open Shortest Path First)和密集模式独立多播协议(PIM-DM:Protocol-Independent Multicast-Dense Mode)等。

    多播路由的第二种类型则假设多播组成员在网络中是稀疏分散的,并且网络不能提供足够的传输带宽,比如Internet上通过ISDN线路连接分散在许多不同地区的大量用户。在这种情况下,广播就会浪费许多不必要的网络带宽从而可能导致严重的网络性能问题。于是稀疏模式多播路由协议必须依赖于具有路由选择能力的技术来建立和维持多播树。稀疏模式主要有基于核心树的多播协议(CBT:Core Based Tree)和稀疏模式独立协议多播(PIM-SM:Protocol-Independent Multicast-Sparse Mode)。

    2.密集模式协议

    (1)距离向量多播路由协议 (DVMRP)

    第一个支持多播功能的路由协议就是距离向量多播路由协议。它已经被广泛地应用在多播骨干网MBONE上。

    DVMRP为每个发送源和目的主机组构建不同的分布树。每个分布树都是一个以多播发送源作为根,以多播接受目的主机作为叶的最小扩展分布树。这个分布树为发送源和组中每个多播接受者之间提供了一个最短路径,这个以“跳数”为单位的最短路径就是DVMRP的量度。当一个发送源要向多播组中发送消息时,一个扩展分布树就根据这个请求而建立,并且使用“广播和修剪”的技术来维持这个扩展分布树。

    扩展分布树构建过程中的选择性发送多播包的具体运作是:当一个路由器接收到一个多播包,它先检查它的单播路由表来查找到多播组发送源的最短路径的接口,如果这个接口就是这个多播包到达的接口,那么路由器就将这个多播组信息记录到它的内部路由表(指明该组数据包应该发送的接口),并且将这个多播包向除了接受到该数据包的路由器以外的其他临近路由器继续发送。如果这个多播包的到达接口不是该路由器到发送源的最短路径的接口,那么这个包就被丢弃。这种机制被称为“反向路径广播”(Reverse-Path Broadcasting)机制,保证了构建的树中不会出现环,而且从发送源到所有接受者都是最短路径。

    对子网中密集分布的多播组来说DVMRP能够很好的运作,但是对于在范围比较大的区域上分散分布的多播组来说,周期性的广播行为会导致严重的性能问题。DVMRP不能支持大型网络中稀疏分散的多播组。

    (2)多播开放最短路径优先 (MOSPF)

    开放最短路径优先(OSPF)是一个单播路由协议,它将数据包在最小开销路径上进行路由传送,这里的开销是表示链路状态的一种量度。除了路径中的跳数以外,其他能够影响路径开销的网络性能参数还有负载平衡信息、应用程序需要的QoS等。

    MOSPF是为单播路由多播使用设计的。MOSPF依赖于OSPF作为单播路由协议,就象DVMRP也包含它自己的单播协议一样。在一个OSPF/MOSPF网络中每个路由器都维持一个最新的全网络拓扑结构图。这个“链路状态”信息被用来构建多播分布树。
     

    每个MOSPF路由器都通过IGMP协议周期性的收集多播组成员关系信息。这些信息和这些链路状态信息被发送到其路由域中的所有其他路由器。路由器将根据它们从临近路由器接收到的这些信息更新他们的内部连接状态信息。由于每个路由器都清楚整个网络的拓扑结构,就能够独立的计算出一个最小开销扩展树,将多播发送源和多播组成员分别作为树的根和叶。这个树就是用来将多播流从发送源发送到多播组成员的路径。

    (3)独立多播密集模式协议(PIM-DM)

    独立多播协议(PIM)是一种标准的多播路由协议,并能够在Internet上提供可扩展的域间多播路由而不依赖于任何单播协议。PIM有两种运行模式,一种是密集分布多播组模式,另一个是稀疏分布多播组模式,前者被称为独立多播密集模式协议(PIM-DM),后者被称为独立多播稀疏模式协议(PIM-SM)。

    PIM-DM有点类似于DVMRP,这两个协议都使用了反向路径多播机制来构建分布树。它们之间的主要不同在于PIM完全不依赖于网络中的单播路由协议而DVMRP依赖于某个相关的单播路由协议机制,并且PIM-DM比DVMRP简单。

    PIM-DM协议和所有的密集模式路由协议一样也是数据驱动的。但是既然PIM-DM不依赖于任何单播路由协议,路由器某个接收端口(就是返回到源的最短路径的端口)接收到的多播数据包被发送到所有下行接口直到不需要的分枝从树中被修剪掉。DVMRP在树构建阶段能够使用单播协议提供的拓扑数据有选择性的向下行发送数据包,PIM-DM则更加倾向于简单性和独立性,甚至不惜增加数据包复制引起的额外开销。

    2.稀疏模式多播路由协议

    当多播组在网络中集中分布或者网络提供足够大带宽的情况下,密集模式多播路由协议是一个有效的方法,当多播组成员在广泛区域内稀疏分布时,就需要另一种方法即稀疏模式多播路由协议将多播流量控制在连接到多播组成员的链路路径上,而不会“泄漏”到不相关的链路路径上,这样既保证了数据传输的安全,又能够有效的控制网络中的总流量和路由器的负载。

    (1)基于核心树的多播协议 (CBT

    和DVMRP和MOSPF为每个“发送源、目的组”对构建最短路径树不同的是,CBT协议只构建一个树给组中所有成员共享,这个树也就被称为共享树。整个多播组的多播通信量都在这个共享树上进行收发而不论发送源有多少或者在什么位置。这种共享树的使用能够极大的减少路由器中的多播状态信息。

    CBT共享树有一个核心路由器用来构建这个树。要加入的路由器发送加入请求给这个核心路由器。核心路由器接收到加入请求后,沿反路径返回一个确认,这样就构成了树的一个分枝。加入请求数据包在被确认之前不需要一直被传送到核心路由器。如果加入请求包在到达核心路由器之前先到达树上的某个路由器,该路由器就接收下这个请求包而不继续向前发送并确认这个请求包。发送请求的路由器就连接到共享树上了。 CBT将多播流量集中在最少数量的链路而不是在一个基于发送源的共享树上。集中在核心路由器上的流量可能会引起多播路由的某些问题。某些版本的CBT支持多个多播核心的使用,和单个多播核心相比多核心更能达到负载平衡。

    (2)独立多播稀疏模式协议 (PIM-SM)

    和CBT相似,PIM-SM被设计成将多播限制在需要收发的路由器上。PIM-SM围绕一个被称为集中点(RP:Rendezvous Point)的路由器构建多播分布树。这个集中点扮演着和CBT核心路由器相同的角色,接收者在集中点能查找到新的发送源。但是PIM-SM比CBT更灵活,CBT的树通常是多播组共享树,PIM-SM中的独立的接收者可以选择是构建组共享树还是最短路径树。

    PIM-SM协议最初先为多播组构建一个组共享树。这个树由连接到集中点的发送者和接收者共同构建,就像CBT协议围绕着核心路由器构建的共享树一样。这共享树建立以后,一个接受者(实际上是最接近这个接收者的路由器)可以选择通过最短路径树改变到发送源的连接。这个操作的过程是通过向发送源发送一个PIM加入请求完成的。一旦从发送源到接收者的最短路径建立了,通过RP的外部分枝就被修剪掉了。

    四、IP多播应用的编程方法
      在实际应用中,编程人员通常需要自己编制底层网络应用程序来实现网上的底层通信,如具体实现IP多播通信的功能。编制底层网络应用程序通常要借助于网络数据通信编程接口,而在不同的操作系统中所提供的网络编程接口是有所不同的,如在Microsoft Windows环境下的网络编程接口就是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多播通信,可将参数dwFlags设置为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用来允许或禁止多播通信时发送出去的通信流量是否也能够在同一个套接字上被接收(即多播返回)。值得注意的是,在Windows 95/98/NT 4中,默认是允许多播返回,但不能设置禁止,否则会出错;只有在Windows 2000以上版本中,才能设置允许/禁止多播返回。
      
      WSAIoctl()函数的命令码SIO_MULTICAST_SCOPE用来设置多播传播的范围,即生存时间TTL。每当多播路由器转发多播数据包时,数据包中的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编程,在程序中应包含“winsock2.h”头文件,并在项目中加入ws2_32.lib的静态库,该静态库应设置在项目属性的“链接器”\“输入”\“附加依赖项”中。
      

      2.在对话框(类名CCMulticastSocketDlg)资源中,设置它的Caption为“WinSock 2多播应用程序”,并添加以下控件:

      静态文本:Caption为“接收到的信息:”;
      编辑框:ID为IDC_RECEIVE_EDIT,Read Only、Auto Vscroll、Vertical Scroll和Multiline属性值都为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属性值为True。


      为该对话框添加新的类CJoinGroupDlg,它的基类为CDialog,然后为该对话框中的三个编辑框分别添加相
    关联的变量,即CSting m_IPAddress、UINT m_nPort、UINT m_nTTL;为复选框添加相关联的BOOL类型的变量m_Loopback。


      4.在CMulticastSocketDlg.h文件的前面添加CJoinGroupDlg的头文件:#include “JoinGroupDlg.h”,并在CCMulticastSocketDlg类中添加了一个CJoinGroupDlg类实例对象m_JoinDlg。

      5.为了能在对话框中接收网络事件通知,应增加一个用户自定义的消息及消息处理函数,具体实现方法如下:在CMulticastSocketDlg.h文件的前面自定义消息:#define WM_SOCK_MSG(WM_USER+166),并在afx_msg块中说明消息处理函数:afx_msg LRESULT OnSocketMsg (WPARAM wParam,LPARAM lParam);在CMulticastSocketDlg.cpp文件中的消息映射块中,使用ON_MESSAGE (WM_SOCK_MSG,OnSocketMsg)宏指令将消息映射到消息处理函数中,并具体实现消息处理函数:LRESULT CCMulticastSocketDlg:: OnSocketMsg(WPARAM wParam,LPARAM lParam){…}。


    该程序的主要代码可参见程序清单,相关函数的详细说明可参看Microsoft MSDN帮助系统。为了节省篇幅,程序中省略了部分自动生成的和用于错误处理的代码。

    程序清单:

    // CMulticastSocketDlg.cpp : 实现文件
    #include "stdafx.h"
    #include "winsock2.h"
    #include "CMulticastSocket.h"
    #include "CMulticastSocketDlg.h"
    ……
    DWORD cbRet;
    SOCKET Sock,SockM; file://UDP套接字,多播套接字
    BOOL bFlag,bJoin;
    SOCKADDR_IN local,Remote,From; file://分别指向本地、多播组和数据来源的IP地址与端口
    int Fromlen;
    char ReceiveBuf[32000]; file://接收缓冲区
    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); file://设置定时器
    Fromlen=sizeof(From);
    bDataReceived=TRUE;
    bJoin=FALSE;
    return TRUE; // 除非设置了控件的焦点,否则返回 TRUE
    }
    ……
    void CCMulticastSocketDlg::OnBnClickedJoinButton() file://加入多播组
    {
    if(m_JoinDlg.DoModal()==IDOK)
    {
    WORD wVersionRequested;
    WSADATA wsaData;
    int 北京中庆;
    wVersionRequested = MAKEWORD(2,2);
    北京中庆 = WSAStartup(wVersionRequested, &wsaData); file://初始化WinSock2资源
    if(北京中庆!= 0){
    AfxMessageBox("不能加载Windows套接字动态链接库,MB_OK");
    return;
    }
    if (LOBYTE(wsaData.wVersion) !=2 || HIBYTE(wsaData.wVersion) !=2){
    AfxMessageBox("WinSock DLL不支持2.0版本,MB_OK");
    WSACleanup( );
    return;
    }
    file://创建一个套接字
    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; file://设置套接字选项,使套接字为可重用端口地址
    setsockopt(Sock,SOL_SOCKET,SO_REUSEADDR,(char*)&bFlag,sizeof(bFlag));

    file://将套接字绑定到用户指定端口及默认的接口
    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));

    file://设置多播数据报传播范围(生存时间TTL)
    WSAIoctl(Sock,SIO_MULTICAST_SCOPE,&m_JoinDlg.m_nTTL,sizeof(int),
    NULL,0,&cbRet,NULL,NULL);
    file://设置多播返回(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);
    file://加入到指定的多播组,并指定为既作为发送者又作为接收者(JL_BOTH)
    SockM=WSAJoinLeaf(Sock,(sockaddr*)&Remote,sizeof(Remote),
    NULL,NULL,NULL,NULL,JL_BOTH);
    WSAAsyncSelect(Sock,m_hWnd,WM_SOCK_MSG,FD_READ); file://注册网络消息及其网络事件
    bJoin=TRUE;
    }
    }

    void CCMulticastSocketDlg::OnBnClickedSendButton() file://多播发送
    {
    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()
    { file://离开多播组
    closesocket(SockM);
    closesocket(Sock);
    WSACleanup();
    m_SendMessage="";
    m_ReceiveMessage="";
    bDataReceived=TRUE;
    bJoin=FALSE;
    UpdateData(FALSE);
    }

    void CCMulticastSocketDlg::OnBnClickedQuitButton()
    { file://退出
    DestroyWindow();
    }

    void CCMulticastSocketDlg::OnTimer(UINT nIDEvent) file://定时器处理函数,实现接收信息的定时更新
    {
    if(bDataReceived)
    {
    m_ReceiveMessage+=ReceiveBuf;
    m_ReceiveMessage+="\r\n";
    bDataReceived=FALSE;
    UpdateData(FALSE);
    }
    CDialog::OnTimer(nIDEvent);
    }

    LRESULT CCMulticastSocketDlg::OnSocketMsg(WPARAM wParam,LPARAM lParam)
    {
    file://检索网络事件
    switch(WSAGETSELECTEVENT(lParam)){
    case FD_READ:
    recvfrom(Sock,ReceiveBuf,32000,0,(sockaddr *)&From,&Fromlen);
    bDataReceived=TRUE; file://设置已接收到一条信息标志
    break;
    }
    return TRUE;
    }

    六、IP多播技术的应用

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

    1.点对多点应用

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

    媒体广播:如演讲、演示、会议等按日程进行的事件。其传统媒体分发手段通常采用电视和广播。这一类应用通常需要一个或多个恒定速率的数据流,当采用多个数据流(如语音和视频)时,往往它们之间需要同步,并且相互之间有不同的优先级。它们往往要求较高的带宽、较小的延时抖动,但是对绝对延时的要求不是很高。

    媒体推送:如新闻标题、天气变化、运动比分等一些非商业关键性的动态变化的信息。它们要求的带宽较低、对延时也没有什么要求。

    信息缓存:如网站信息、执行代码和其他基于文件的分布式复制或缓存更新。它们对带宽的要求一般,对延时的要求也一般。

    事件通知:如网络时间、组播会话日程、随机数字、密钥、配置更新、有效范围的网络警报或其他有用信息。它们对带宽的需求有所不同,但是一般都比较低,对延时的要求也一般。

    状态监视:如股票价格、传感设备、安全系统、生产信息或其他实时信息。这类带宽要求根据采样周期和精度有所不同,可能会有恒定速率带宽或突发带宽要求,通常对带宽和延时的要求一般。

    2.多点对点的应用

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

    资源查找:如服务定位,它要求的带宽较低,对时延的要求一般。

    数据收集: 它是点对多点应用中状态监视应用的反向过程。它可能由多个传感设备把数据发回给一个数据收集主机。带宽要求根据采样周期和精度有所不同,可能会有恒定速率带宽或突发带宽要求,通常这类应用对带宽和延时的要求一般。

    网络竞拍:拍卖者拍卖产品,而多个竞拍者把标价发回给拍卖者。

    信息询问:询问者发送一个询问,所有被询问者返回应答。通常这对带宽的要求较低,对延时不太敏感。

    Juke Box:如支持准点播(Near-On-Demand)的音视频倒放。通常接收者采用“带外的”协议机制(如HTTP、RTSP、SMTP,也可以采用组播方式)发送倒放请求给一个调度队列。它对带宽的要求较高,对延时的要求一般。

    3.多点对多点的应用

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

    多点会议: 通常音/视频和文本应用构成多点会议应用。在多点会议中,不同的数据流拥有不同的优先级。传统的多点会议采用专门的多点控制单元来协调和分配它们,采用多播可以直接由任何一个发送者向所有接收者发送,多点控制单元用来控制当前发言权。这类应用对带宽和延时要求都比较高。

    资源同步:如日程、目录、信息等分布数据库的同步。它们对带宽和延时的要求一般。

    并行处理:如分布式并行处理。它对带宽和延时的要求都比较高。

    协同处理:如共享文档的编辑。它对带宽和延时的要求一般。

    远程学习:这实际上是媒体广播应用加上对上行数据流(允许学生向老师提问)的支持。它对带宽和延时的要求一般。
    讨论组:类似于基于文本的多点会议,还可以提供一些模拟的表达。

    分布式交互模拟(DIS):它对带宽和时延的要求较高。

    多人游戏: 多人游戏是一种带讨论组能力的简单分布式交互模拟。它对带宽和时延的要求都比较高。

    Jam Session:这是一种音频编码共享应用。它对带宽和时延的要求都比较高。

    IP多播带入了许多新的应用并减少了网络的拥塞和服务器的负担。目前IP多播的应用范围还不够大,但它能够降低占用带宽,减轻服务器负荷,并能改善传送数据的质量,尤其适用于需要大量带宽的多媒体应用,如音频、视频等。这项新技术已成为当前网络界的热门话题,并将从根本上改变网络的体系结构。

  • 相关阅读:
    【洛谷P1962】斐波那契数列
    【洛谷P3390】【模板】矩阵快速幂
    【洛谷P3070】[USACO13JAN]岛游记Island Travels
    【NOIp模拟赛】antipalindrome
    【洛谷P3930】SAC E#1
    【洛谷P3928】SAC E#1
    【洛谷P3927】SAC E#1
    【NOIp模拟赛】binary
    【NOIp模拟赛】value
    【洛谷P2341】[HAOI2006]受欢迎的牛
  • 原文地址:https://www.cnblogs.com/yunbo/p/584208.html
Copyright © 2020-2023  润新知