【miscellaneous】IP多播技术及其编程
生活随笔
收集整理的這篇文章主要介紹了
【miscellaneous】IP多播技术及其编程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
標??題: 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;?
}?
發信站: 幽幽黃桷蘭 (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多播技术及其编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 69道Spring面试题和答案
- 下一篇: Mac平台下Opencv开发环境搭建