【miscellaneous】IP多播技术及其编程
生活随笔
收集整理的這篇文章主要介紹了
【miscellaneous】IP多播技术及其编程
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
標(biāo)??題: IP多播技術(shù)及其編程?
發(fā)信站: 幽幽黃桷蘭 (Mon Jun 16 10:35:39 2003)?
轉(zhuǎn)信站: SMTH!maily.cic.tsinghua.edu.cn!news2.uestc.edu.cn!CQUPT?
??
IP多播(也稱多址廣播或組播)技術(shù),是一種允許一臺或多臺主機(jī)(多播源)發(fā)送單一?
數(shù)據(jù)包到多臺主機(jī)(一次的,同時(shí)的)的TCP/IP網(wǎng)絡(luò)技術(shù)。多播作為一點(diǎn)對多點(diǎn)的通信?
,是節(jié)省網(wǎng)絡(luò)帶寬的有效方法之一。在網(wǎng)絡(luò)音頻/視頻廣播的應(yīng)用中,當(dāng)需要將一個(gè)節(jié)點(diǎn)?
的信號傳送到多個(gè)節(jié)點(diǎn)時(shí),無論是采用重復(fù)點(diǎn)對點(diǎn)通信方式,還是采用廣播方式,都會?
嚴(yán)重浪費(fèi)網(wǎng)絡(luò)帶寬,只有多播才是最好的選擇。多播能使一個(gè)或多個(gè)多播源只把數(shù)據(jù)包?
發(fā)送給特定的多播組,而只有加入該多播組的主機(jī)才能接收到數(shù)據(jù)包。目前,IP多播技?
術(shù)被廣泛應(yīng)用在網(wǎng)絡(luò)音頻/視頻廣播、AOD/VOD、網(wǎng)絡(luò)視頻會議、多媒體遠(yuǎn)程教育、“pu?
sh”技術(shù)(如股票行情等)和虛擬現(xiàn)實(shí)游戲等方面。?
一、IP多播技術(shù)簡介?
1.IP多播地址和多播組?
IP多播通信必須依賴于IP多播地址,在IPv4中它是一個(gè)D類IP地址,范圍從224.0.0.0到?
239.255.255.255,并被劃分為局部鏈接多播地址、預(yù)留多播地址和管理權(quán)限多播地址三?
類。其中,局部鏈接多播地址范圍在224.0.0.0~224.0.0.255,這是為路由協(xié)議和其它用?
途保留的地址,路由器并不轉(zhuǎn)發(fā)屬于此范圍的IP包;預(yù)留多播地址為224.0.1.0~238.25?
5.255.255,可用于全球范圍(如Internet)或網(wǎng)絡(luò)協(xié)議;管理權(quán)限多播地址為239.0.0?
.0~239.255.255.255,可供組織內(nèi)部使用,類似于私有IP地址,不能用于Internet,可?
限制多播范圍。?
使用同一個(gè)IP多播地址接收多播數(shù)據(jù)包的所有主機(jī)構(gòu)成了一個(gè)主機(jī)組,也稱為多播組。?
一個(gè)多播組的成員是隨時(shí)變動(dòng)的,一臺主機(jī)可以隨時(shí)加入或離開多播組,多播組成員的?
數(shù)目和所在的地理位置也不受限制,一臺主機(jī)也可以屬于幾個(gè)多播組。此外,不屬于某?
一個(gè)多播組的主機(jī)也可以向該多播組發(fā)送數(shù)據(jù)包。?
2.IP多播技術(shù)的硬件支持?
要實(shí)現(xiàn)IP多播通信,要求介于多播源和接收者之間的路由器、集線器、交換機(jī)以及主機(jī)?
均需支持IP多播。目前,IP多播技術(shù)已得到硬件、軟件廠商的廣泛支持。?
(1)主機(jī)?
支持IP多播通信的平臺包括Windows CE 2.1、Windows 95、Windows 98、Windows NT 4?
和Windows 2000等,運(yùn)行這些操作系統(tǒng)的主機(jī)都可以進(jìn)行IP多播通信。此外,新生產(chǎn)的?
網(wǎng)卡也幾乎都提供了對IP多播的支持。?
(2)集線器和交換機(jī)?
目前大多數(shù)集線器、交換機(jī)只是簡單地把多播數(shù)據(jù)當(dāng)成廣播來發(fā)送接收,但一些中、高?
檔交換機(jī)提供了對IP多播的支持。例如,在3COM SuperStack 3 Swith 3300交換機(jī)上可?
啟用802.1p或IGMP多播過濾功能,只為已偵測到IGMP數(shù)據(jù)包的端口轉(zhuǎn)發(fā)多播數(shù)據(jù)包。?
(3)路由器?
多播通信要求多播源節(jié)點(diǎn)和目的節(jié)點(diǎn)之間的所有路由器必須提供對Internet組管理協(xié)議?
(IGMP)、多播路由協(xié)議(如PIM、DVMRP等)的支持。?
當(dāng)一臺主機(jī)欲加入某個(gè)多播組時(shí),會發(fā)出“主機(jī)成員報(bào)告”的IGMP消息通知多播路由器?
。當(dāng)多播路由器接收到發(fā)給那個(gè)多播組的數(shù)據(jù)時(shí),便會將其轉(zhuǎn)發(fā)給所有的多播主機(jī)。多?
播路由器還會周期性地發(fā)出“主機(jī)成員查詢”的IGMP消息,向子網(wǎng)查詢多播主機(jī),若發(fā)?
現(xiàn)某個(gè)多播組已沒有任何成員,則停止轉(zhuǎn)發(fā)該多播組的數(shù)據(jù)。此外,當(dāng)支持IGMP v2的主?
機(jī)(如Windows 98/2000計(jì)算機(jī))退出某個(gè)多播組時(shí),還會向路由器發(fā)送一條“離開組?
”的IGMP消息,以通知路由器停止轉(zhuǎn)發(fā)該多播組的數(shù)據(jù)。但只有當(dāng)子網(wǎng)上所有主機(jī)都退?
出某個(gè)多播組時(shí),路由器才會停止向該子網(wǎng)轉(zhuǎn)發(fā)該多播組的數(shù)據(jù)。?
使用多播路由協(xié)議,路由器可建立起從多播源節(jié)點(diǎn)到所有目的節(jié)點(diǎn)的多播路由表,從而?
實(shí)現(xiàn)在子網(wǎng)間轉(zhuǎn)發(fā)多播數(shù)據(jù)包。例如,PIM(協(xié)議獨(dú)立多播)就是一種多播路由協(xié)議,它?
有兩種類型:稀疏模式(sparse-mode)和密集模式(dense-mode)。以Cisco 2621路由?
器為例,啟用IP多播轉(zhuǎn)發(fā)功能的基本設(shè)置如下:?
c2621(config)# ip multicast-routing 啟動(dòng)IP多播,使路由器成為一個(gè)多播路由器?
c2621(config)# int f0/0 配置快速以太網(wǎng)端口0?
c2621(config-if)# ip pim dense-mode(或sparse-mode)啟動(dòng)PIM,同時(shí)激活I(lǐng)GMP協(xié)議?
??
c2621(config-if)# int f0/1 配置快速以太網(wǎng)端口1?
c2621(config-if)# ip pim dense-mode(或sparse-mode)?
二、IP多播應(yīng)用的編程方法?
在實(shí)際應(yīng)用中,編程人員通常需要自己編制底層網(wǎng)絡(luò)應(yīng)用程序來實(shí)現(xiàn)網(wǎng)上的底層通信,?
如具體實(shí)現(xiàn)IP多播通信的功能。編制底層網(wǎng)絡(luò)應(yīng)用程序通常要借助于網(wǎng)絡(luò)數(shù)據(jù)通信編程?
接口,而在不同的操作系統(tǒng)中所提供的網(wǎng)絡(luò)編程接口是有所不同的,如在Microsoft Wi?
ndows環(huán)境下的網(wǎng)絡(luò)編程接口就是Windows套接字(Windows Socket,簡稱Winsock)。?
Winsock提供了包括TCP/IP、IPX等多種通信協(xié)議下的編程接口。不同的Windows版本支持?
不同的Winsock版本,其中Windows 95等早期版本本身只支持Winsock1.1(16位)下的編?
程(可以通過安裝相關(guān)的軟件包使其支持Winsock2.0),而Windows98、Windows NT4.0?
、Windows 2000則直接支持Winsock2.0(32位)。Winsock2.0是Winsock1.1的擴(kuò)展,除?
兼容Winsock1.1 API外,還定義了一套可支持IP多播的與協(xié)議無關(guān)的API。?
使用Winsock 2.0實(shí)現(xiàn)IP多播的一般步驟如下:?
1.初始化Winsock資源?
在使用Winsock之前,必須調(diào)用WSAStartup()函數(shù)初始化Windows Sockets DLL。它允許?
應(yīng)用程序或DLL指定Windows Sockets API要求的版本。?
2.創(chuàng)建套接字?
調(diào)用WSASocket()函數(shù)可以創(chuàng)建一個(gè)使用UDP協(xié)議的套接字,它是加入多播組的初始化套?
接字,并且以后數(shù)據(jù)的發(fā)送和接收都在該套接字上進(jìn)行。針對IP多播通信,可將參數(shù)dw?
Flags設(shè)置為WSA_FLAG_MULTIPOINT_C_LEAF、WSA_FLAG_MULTIPOINT_D_LEAF和WSA_FLAG_?
OVERLAPPED的位和,指明IP多播通信在控制層面和數(shù)據(jù)層面都是“無根的”,只存在葉?
節(jié)點(diǎn),它們可以任意加入一個(gè)多播組,而且從一個(gè)葉節(jié)點(diǎn)發(fā)送的數(shù)據(jù)會傳送到每一個(gè)葉?
節(jié)點(diǎn)(包括它自己);創(chuàng)建的套接字具有重疊屬性。?
3.設(shè)置套接字的選項(xiàng)?
調(diào)用setsockopt()函數(shù)為套接字設(shè)置SO_REUSEADDR選項(xiàng),以允許套接字綁扎到一個(gè)已在?
使用的地址上。?
4.綁定套接字?
調(diào)用bind()函數(shù)綁定套接字,從而將創(chuàng)建好的套接字與本地地址和本地端口聯(lián)系起來。?
對于多播通信來說,發(fā)送和接收數(shù)據(jù)通常采用同一個(gè)端口。?
5.設(shè)置多播套接字的模式?
WSAIoctl()函數(shù)的命令碼SIO_MULTICAST_LOOP用來允許或禁止多播通信時(shí)發(fā)送出去的通?
信流量是否也能夠在同一個(gè)套接字上被接收(即多播返回)。值得注意的是,在Window?
s 95/98/NT 4中,默認(rèn)是允許多播返回,但不能設(shè)置禁止,否則會出錯(cuò);只有在Window?
s 2000以上版本中,才能設(shè)置允許/禁止多播返回。?
WSAIoctl()函數(shù)的命令碼SIO_MULTICAST_SCOPE用來設(shè)置多播傳播的范圍,即生存時(shí)間T?
TL。每當(dāng)多播路由器轉(zhuǎn)發(fā)多播數(shù)據(jù)包時(shí),數(shù)據(jù)包中的TTL值都會被減1,若數(shù)據(jù)包的TTL減?
少到0,則路由器將拋棄該數(shù)據(jù)包。TTL的值是多少,多播數(shù)據(jù)便最多能經(jīng)過多少個(gè)多播?
路由器。例如,TTL值為0,則多播只能在本地主機(jī)的多個(gè)套接字間傳播,而不能傳播到?
“網(wǎng)線”上;TTL值為1(默認(rèn)值),則多播數(shù)據(jù)遇到第一個(gè)路由器,便會被它“無情”?
地丟棄,不允許傳出本地網(wǎng)絡(luò)之外,即只有同一個(gè)網(wǎng)絡(luò)內(nèi)的多播組成員才能收到多播數(shù)?
據(jù)。?
6.加入一個(gè)多播組?
調(diào)用WSAJoinLeaf()函數(shù)可加入一個(gè)多播組并指定角色(發(fā)送者/接收者)。調(diào)用時(shí),參?
數(shù)dwFlags可指定套接字作為發(fā)送者(JL_SENDER_ONLY)、接收者(JL_RECEIVER_ONLY)?
或身兼兩者(JL_BOTH)。調(diào)用成功后會返回一個(gè)多播套接字,調(diào)用closesocket()函數(shù)?
關(guān)閉該套接字就離開了多播組,此時(shí)可以調(diào)用WSAJoinLeaf()函數(shù)再次加入多播組。注意?
,對多播組數(shù)據(jù)的接收和發(fā)送不能在該套接字上完成。?
7.向多播組發(fā)送數(shù)據(jù)?
調(diào)用sendto()函數(shù),可在指定的UDP套接字上向指定的多播組發(fā)送多播數(shù)據(jù)。調(diào)用時(shí),參?
數(shù)to應(yīng)指向多播組的IP地址。值得注意的是,若一個(gè)應(yīng)用程序只是打算給多播組發(fā)送數(shù)?
據(jù),便不必加入一個(gè)多播組。?
8.等待事件?
調(diào)用WSAAsyncSelect()函數(shù),使套接字置于非阻塞模式,這時(shí)應(yīng)用程序就可在該套接字?
上接收以Windows消息為基礎(chǔ)的網(wǎng)絡(luò)事件通知。例如,若參數(shù)lEvent值為FD_READ,則應(yīng)?
用程序可在套接字上接收到“數(shù)據(jù)正等待被讀入”的通知。?
9.從多播組接收數(shù)據(jù)?
調(diào)用recvfrom函數(shù),可在指定的UDP套接字上讀取輸入數(shù)據(jù)。多播通信中數(shù)據(jù)的發(fā)送與接?
收一般采用同一個(gè)端口,因此其發(fā)送套接字和接收套接字是一樣的。?
10.關(guān)閉套接字,釋放Winsock資源。?
在多播通信結(jié)束后,先調(diào)用closesocket()函數(shù)關(guān)閉多播套接字和UDP套接字,然后調(diào)用?
WSACleanup()函數(shù)結(jié)束對Windows Sockets DLL的使用。?
三、應(yīng)用實(shí)例?
為了說明IP多播技術(shù)的應(yīng)用方法,本人在Visual C++.NET環(huán)境下設(shè)計(jì)了一個(gè)簡單的基于?
Windows Socket 2的IP多播應(yīng)用程序,通過該例子讀者可以掌握IP多播應(yīng)用程序設(shè)計(jì)的?
一般方法。該程序的具體設(shè)計(jì)方法如下:?
1.在Visual Studio.NET中建立一個(gè)基于對話框的MFC項(xiàng)目CMulticastSocket。注意在“?
高級功能”設(shè)置中不要選擇“Windows套接字”,這是因?yàn)镸FC只支持Windows Socket 1?
而不支持Windows Socket 2。為了能使用Winsock 2 API編程,在程序中應(yīng)包含“winso?
ck2.h”頭文件,并在項(xiàng)目中加入ws2_32.lib的靜態(tài)庫,該靜態(tài)庫應(yīng)設(shè)置在項(xiàng)目屬性的“?
鏈接器”\“輸入”\“附加依賴項(xiàng)”中。?
2.在對話框(類名CCMulticastSocketDlg)資源中,設(shè)置它的Caption為“WinSock 2多?
播應(yīng)用程序”,并添加以下控件:?
靜態(tài)文本:Caption為“接收到的信息:”;?
編輯框:ID為IDC_RECEIVE_EDIT,Read Only、Auto Vscroll、Vertical Scroll和Mult?
iline屬性值都為True?
靜態(tài)文本:Caption為“發(fā)送的信息:”?
編輯框:ID為IDC_SEND_EDIT?
第一個(gè)按鈕:Caption為“加入多播組(&J)”,ID為IDC_JOIN_BUTTON?
第二個(gè)按鈕:Caption為“多播發(fā)送(&S)”,ID為IDC_SEND_BUTTON?
第三個(gè)按鈕:Caption為“離開多播組(&L)”,ID為IDC_LEAVE_BUTTON?
第四個(gè)按鈕:Caption為“退出(&Q)”,ID為IDC_QUIT_BUTTON?
為兩個(gè)編輯框分別添加相關(guān)聯(lián)的CString類型的變量m_SendMessage和m_ReceiveMessage?
;為四個(gè)按鈕添加相應(yīng)的消息處理函數(shù);為對話框添加定時(shí)器消息(用于定時(shí)顯示接收?
到的消息)及其消息處理函數(shù)。?
3.添加一個(gè)新的對話框資源,設(shè)置它的Caption為“加入多播組”,保留默認(rèn)的兩個(gè)按?
鈕控件,同時(shí)添加添加以下控件:?
靜態(tài)文本:Caption為“IP多播組地址:”?
編輯框:ID為IDC_IPADDRESS_EDIT?
靜態(tài)文本:Caption為“IP多播端口:”?
編輯框:ID為IDC_PORT_EDIT?
靜態(tài)文本:Caption為“生存時(shí)間:”?
編輯框:ID為IDC_TTL_EDIT?
復(fù)選框:Caption為“多播返回:”,ID為IDC_LOOPBACK_CHECK,Left Text屬性值為Tr?
ue。?
為該對話框添加新的類CJoinGroupDlg,它的基類為CDialog,然后為該對話框中的三個(gè)?
編輯框分別添加相關(guān)聯(lián)的變量,即CSting m_IPAddress、UINT m_nPort、UINT m_nTTL;?
為復(fù)選框添加相關(guān)聯(lián)的BOOL類型的變量m_Loopback。?
4.在CMulticastSocketDlg.h文件的前面添加CJoinGroupDlg的頭文件:#include “Jo?
inGroupDlg.h”,并在CCMulticastSocketDlg類中添加了一個(gè)CJoinGroupDlg類實(shí)例對象?
m_JoinDlg。?
5.為了能在對話框中接收網(wǎng)絡(luò)事件通知,應(yīng)增加一個(gè)用戶自定義的消息及消息處理函數(shù)?
,具體實(shí)現(xiàn)方法如下:在CMulticastSocketDlg.h文件的前面自定義消息:#define WM_?
SOCK_MSG(WM_USER+166),并在afx_msg塊中說明消息處理函數(shù):afx_msg LRESULT OnSo?
cketMsg (WPARAM wParam,LPARAM lParam);在CMulticastSocketDlg.cpp文件中的消息?
映射塊中,使用ON_MESSAGE (WM_SOCK_MSG,OnSocketMsg)宏指令將消息映射到消息處理?
函數(shù)中,并具體實(shí)現(xiàn)消息處理函數(shù):LRESULT CCMulticastSocketDlg:: OnSocketMsg(W?
PARAM wParam,LPARAM lParam){…}。?
該程序的主要代碼可參見程序清單,相關(guān)函數(shù)的詳細(xì)說明可參看Microsoft MSDN幫助系?
統(tǒng)。為了節(jié)省篇幅,程序中省略了部分自動(dòng)生成的和用于錯(cuò)誤處理的代碼。?
程序清單:?
// CMulticastSocketDlg.cpp : 實(shí)現(xiàn)文件?
#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; //分別指向本地、多播組和數(shù)據(jù)來源的IP地址與端口?
??
int Fromlen;?
char ReceiveBuf[32000]; //接收緩沖區(qū)?
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); //設(shè)置定時(shí)器?
Fromlen=sizeof(From);?
bDataReceived=TRUE;?
bJoin=FALSE;?
return TRUE; // 除非設(shè)置了控件的焦點(diǎn),否則返回 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套接字動(dòng)態(tài)鏈接庫,MB_OK");?
return;?
}?
if (LOBYTE(wsaData.wVersion) !=2 || HIBYTE(wsaData.wVersion) !=2){?
AfxMessageBox("WinSock DLL不支持2.0版本,MB_OK");?
WSACleanup( );?
return;?
}?
//創(chuàng)建一個(gè)套接字?
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; //設(shè)置套接字選項(xiàng),使套接字為可重用端口地址?
setsockopt(Sock,SOL_SOCKET,SO_REUSEADDR,(char*)&bFlag,sizeof(bFlag));?
//將套接字綁定到用戶指定端口及默認(rèn)的接口?
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));?
//設(shè)置多播數(shù)據(jù)報(bào)傳播范圍(生存時(shí)間TTL)?
WSAIoctl(Sock,SIO_MULTICAST_SCOPE,&m_JoinDlg.m_nTTL,sizeof(int),?
NULL,0,&cbRet,NULL,NULL);?
//設(shè)置多播返回(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);?
//加入到指定的多播組,并指定為既作為發(fā)送者又作為接收者(JL_BOTH)?
SockM=WSAJoinLeaf(Sock,(sockaddr*)&Remote,sizeof(Remote),?
NULL,NULL,NULL,NULL,JL_BOTH);?
WSAAsyncSelect(Sock,m_hWnd,WM_SOCK_MSG,FD_READ); //注冊網(wǎng)絡(luò)消息及其網(wǎng)絡(luò)事件?
bJoin=TRUE;?
}?
}?
void CCMulticastSocketDlg::OnBnClickedSendButton() //多播發(fā)送?
{?
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) //定時(shí)器處理函數(shù),實(shí)現(xiàn)接收?
信息的定時(shí)更新?
{?
if(bDataReceived)?
{?
m_ReceiveMessage+=ReceiveBuf;?
m_ReceiveMessage+="\r\n";?
bDataReceived=FALSE;?
UpdateData(FALSE);?
}?
CDialog::OnTimer(nIDEvent);?
}?
LRESULT CCMulticastSocketDlg::OnSocketMsg(WPARAM wParam,LPARAM lParam)?
{?
//檢索網(wǎng)絡(luò)事件?
switch(WSAGETSELECTEVENT(lParam)){?
case FD_READ:?
recvfrom(Sock,ReceiveBuf,32000,0,(sockaddr *)&From,&Fromlen);?
bDataReceived=TRUE; //設(shè)置已接收到一條信息標(biāo)志?
break;?
}?
return TRUE;?
}?
發(fā)信站: 幽幽黃桷蘭 (Mon Jun 16 10:35:39 2003)?
轉(zhuǎn)信站: SMTH!maily.cic.tsinghua.edu.cn!news2.uestc.edu.cn!CQUPT?
??
IP多播(也稱多址廣播或組播)技術(shù),是一種允許一臺或多臺主機(jī)(多播源)發(fā)送單一?
數(shù)據(jù)包到多臺主機(jī)(一次的,同時(shí)的)的TCP/IP網(wǎng)絡(luò)技術(shù)。多播作為一點(diǎn)對多點(diǎn)的通信?
,是節(jié)省網(wǎng)絡(luò)帶寬的有效方法之一。在網(wǎng)絡(luò)音頻/視頻廣播的應(yīng)用中,當(dāng)需要將一個(gè)節(jié)點(diǎn)?
的信號傳送到多個(gè)節(jié)點(diǎn)時(shí),無論是采用重復(fù)點(diǎn)對點(diǎn)通信方式,還是采用廣播方式,都會?
嚴(yán)重浪費(fèi)網(wǎng)絡(luò)帶寬,只有多播才是最好的選擇。多播能使一個(gè)或多個(gè)多播源只把數(shù)據(jù)包?
發(fā)送給特定的多播組,而只有加入該多播組的主機(jī)才能接收到數(shù)據(jù)包。目前,IP多播技?
術(shù)被廣泛應(yīng)用在網(wǎng)絡(luò)音頻/視頻廣播、AOD/VOD、網(wǎng)絡(luò)視頻會議、多媒體遠(yuǎn)程教育、“pu?
sh”技術(shù)(如股票行情等)和虛擬現(xiàn)實(shí)游戲等方面。?
一、IP多播技術(shù)簡介?
1.IP多播地址和多播組?
IP多播通信必須依賴于IP多播地址,在IPv4中它是一個(gè)D類IP地址,范圍從224.0.0.0到?
239.255.255.255,并被劃分為局部鏈接多播地址、預(yù)留多播地址和管理權(quán)限多播地址三?
類。其中,局部鏈接多播地址范圍在224.0.0.0~224.0.0.255,這是為路由協(xié)議和其它用?
途保留的地址,路由器并不轉(zhuǎn)發(fā)屬于此范圍的IP包;預(yù)留多播地址為224.0.1.0~238.25?
5.255.255,可用于全球范圍(如Internet)或網(wǎng)絡(luò)協(xié)議;管理權(quán)限多播地址為239.0.0?
.0~239.255.255.255,可供組織內(nèi)部使用,類似于私有IP地址,不能用于Internet,可?
限制多播范圍。?
使用同一個(gè)IP多播地址接收多播數(shù)據(jù)包的所有主機(jī)構(gòu)成了一個(gè)主機(jī)組,也稱為多播組。?
一個(gè)多播組的成員是隨時(shí)變動(dòng)的,一臺主機(jī)可以隨時(shí)加入或離開多播組,多播組成員的?
數(shù)目和所在的地理位置也不受限制,一臺主機(jī)也可以屬于幾個(gè)多播組。此外,不屬于某?
一個(gè)多播組的主機(jī)也可以向該多播組發(fā)送數(shù)據(jù)包。?
2.IP多播技術(shù)的硬件支持?
要實(shí)現(xiàn)IP多播通信,要求介于多播源和接收者之間的路由器、集線器、交換機(jī)以及主機(jī)?
均需支持IP多播。目前,IP多播技術(shù)已得到硬件、軟件廠商的廣泛支持。?
(1)主機(jī)?
支持IP多播通信的平臺包括Windows CE 2.1、Windows 95、Windows 98、Windows NT 4?
和Windows 2000等,運(yùn)行這些操作系統(tǒng)的主機(jī)都可以進(jìn)行IP多播通信。此外,新生產(chǎn)的?
網(wǎng)卡也幾乎都提供了對IP多播的支持。?
(2)集線器和交換機(jī)?
目前大多數(shù)集線器、交換機(jī)只是簡單地把多播數(shù)據(jù)當(dāng)成廣播來發(fā)送接收,但一些中、高?
檔交換機(jī)提供了對IP多播的支持。例如,在3COM SuperStack 3 Swith 3300交換機(jī)上可?
啟用802.1p或IGMP多播過濾功能,只為已偵測到IGMP數(shù)據(jù)包的端口轉(zhuǎn)發(fā)多播數(shù)據(jù)包。?
(3)路由器?
多播通信要求多播源節(jié)點(diǎn)和目的節(jié)點(diǎn)之間的所有路由器必須提供對Internet組管理協(xié)議?
(IGMP)、多播路由協(xié)議(如PIM、DVMRP等)的支持。?
當(dāng)一臺主機(jī)欲加入某個(gè)多播組時(shí),會發(fā)出“主機(jī)成員報(bào)告”的IGMP消息通知多播路由器?
。當(dāng)多播路由器接收到發(fā)給那個(gè)多播組的數(shù)據(jù)時(shí),便會將其轉(zhuǎn)發(fā)給所有的多播主機(jī)。多?
播路由器還會周期性地發(fā)出“主機(jī)成員查詢”的IGMP消息,向子網(wǎng)查詢多播主機(jī),若發(fā)?
現(xiàn)某個(gè)多播組已沒有任何成員,則停止轉(zhuǎn)發(fā)該多播組的數(shù)據(jù)。此外,當(dāng)支持IGMP v2的主?
機(jī)(如Windows 98/2000計(jì)算機(jī))退出某個(gè)多播組時(shí),還會向路由器發(fā)送一條“離開組?
”的IGMP消息,以通知路由器停止轉(zhuǎn)發(fā)該多播組的數(shù)據(jù)。但只有當(dāng)子網(wǎng)上所有主機(jī)都退?
出某個(gè)多播組時(shí),路由器才會停止向該子網(wǎng)轉(zhuǎn)發(fā)該多播組的數(shù)據(jù)。?
使用多播路由協(xié)議,路由器可建立起從多播源節(jié)點(diǎn)到所有目的節(jié)點(diǎn)的多播路由表,從而?
實(shí)現(xiàn)在子網(wǎng)間轉(zhuǎn)發(fā)多播數(shù)據(jù)包。例如,PIM(協(xié)議獨(dú)立多播)就是一種多播路由協(xié)議,它?
有兩種類型:稀疏模式(sparse-mode)和密集模式(dense-mode)。以Cisco 2621路由?
器為例,啟用IP多播轉(zhuǎn)發(fā)功能的基本設(shè)置如下:?
c2621(config)# ip multicast-routing 啟動(dòng)IP多播,使路由器成為一個(gè)多播路由器?
c2621(config)# int f0/0 配置快速以太網(wǎng)端口0?
c2621(config-if)# ip pim dense-mode(或sparse-mode)啟動(dòng)PIM,同時(shí)激活I(lǐng)GMP協(xié)議?
??
c2621(config-if)# int f0/1 配置快速以太網(wǎng)端口1?
c2621(config-if)# ip pim dense-mode(或sparse-mode)?
二、IP多播應(yīng)用的編程方法?
在實(shí)際應(yīng)用中,編程人員通常需要自己編制底層網(wǎng)絡(luò)應(yīng)用程序來實(shí)現(xiàn)網(wǎng)上的底層通信,?
如具體實(shí)現(xiàn)IP多播通信的功能。編制底層網(wǎng)絡(luò)應(yīng)用程序通常要借助于網(wǎng)絡(luò)數(shù)據(jù)通信編程?
接口,而在不同的操作系統(tǒng)中所提供的網(wǎng)絡(luò)編程接口是有所不同的,如在Microsoft Wi?
ndows環(huán)境下的網(wǎng)絡(luò)編程接口就是Windows套接字(Windows Socket,簡稱Winsock)。?
Winsock提供了包括TCP/IP、IPX等多種通信協(xié)議下的編程接口。不同的Windows版本支持?
不同的Winsock版本,其中Windows 95等早期版本本身只支持Winsock1.1(16位)下的編?
程(可以通過安裝相關(guān)的軟件包使其支持Winsock2.0),而Windows98、Windows NT4.0?
、Windows 2000則直接支持Winsock2.0(32位)。Winsock2.0是Winsock1.1的擴(kuò)展,除?
兼容Winsock1.1 API外,還定義了一套可支持IP多播的與協(xié)議無關(guān)的API。?
使用Winsock 2.0實(shí)現(xiàn)IP多播的一般步驟如下:?
1.初始化Winsock資源?
在使用Winsock之前,必須調(diào)用WSAStartup()函數(shù)初始化Windows Sockets DLL。它允許?
應(yīng)用程序或DLL指定Windows Sockets API要求的版本。?
2.創(chuàng)建套接字?
調(diào)用WSASocket()函數(shù)可以創(chuàng)建一個(gè)使用UDP協(xié)議的套接字,它是加入多播組的初始化套?
接字,并且以后數(shù)據(jù)的發(fā)送和接收都在該套接字上進(jìn)行。針對IP多播通信,可將參數(shù)dw?
Flags設(shè)置為WSA_FLAG_MULTIPOINT_C_LEAF、WSA_FLAG_MULTIPOINT_D_LEAF和WSA_FLAG_?
OVERLAPPED的位和,指明IP多播通信在控制層面和數(shù)據(jù)層面都是“無根的”,只存在葉?
節(jié)點(diǎn),它們可以任意加入一個(gè)多播組,而且從一個(gè)葉節(jié)點(diǎn)發(fā)送的數(shù)據(jù)會傳送到每一個(gè)葉?
節(jié)點(diǎn)(包括它自己);創(chuàng)建的套接字具有重疊屬性。?
3.設(shè)置套接字的選項(xiàng)?
調(diào)用setsockopt()函數(shù)為套接字設(shè)置SO_REUSEADDR選項(xiàng),以允許套接字綁扎到一個(gè)已在?
使用的地址上。?
4.綁定套接字?
調(diào)用bind()函數(shù)綁定套接字,從而將創(chuàng)建好的套接字與本地地址和本地端口聯(lián)系起來。?
對于多播通信來說,發(fā)送和接收數(shù)據(jù)通常采用同一個(gè)端口。?
5.設(shè)置多播套接字的模式?
WSAIoctl()函數(shù)的命令碼SIO_MULTICAST_LOOP用來允許或禁止多播通信時(shí)發(fā)送出去的通?
信流量是否也能夠在同一個(gè)套接字上被接收(即多播返回)。值得注意的是,在Window?
s 95/98/NT 4中,默認(rèn)是允許多播返回,但不能設(shè)置禁止,否則會出錯(cuò);只有在Window?
s 2000以上版本中,才能設(shè)置允許/禁止多播返回。?
WSAIoctl()函數(shù)的命令碼SIO_MULTICAST_SCOPE用來設(shè)置多播傳播的范圍,即生存時(shí)間T?
TL。每當(dāng)多播路由器轉(zhuǎn)發(fā)多播數(shù)據(jù)包時(shí),數(shù)據(jù)包中的TTL值都會被減1,若數(shù)據(jù)包的TTL減?
少到0,則路由器將拋棄該數(shù)據(jù)包。TTL的值是多少,多播數(shù)據(jù)便最多能經(jīng)過多少個(gè)多播?
路由器。例如,TTL值為0,則多播只能在本地主機(jī)的多個(gè)套接字間傳播,而不能傳播到?
“網(wǎng)線”上;TTL值為1(默認(rèn)值),則多播數(shù)據(jù)遇到第一個(gè)路由器,便會被它“無情”?
地丟棄,不允許傳出本地網(wǎng)絡(luò)之外,即只有同一個(gè)網(wǎng)絡(luò)內(nèi)的多播組成員才能收到多播數(shù)?
據(jù)。?
6.加入一個(gè)多播組?
調(diào)用WSAJoinLeaf()函數(shù)可加入一個(gè)多播組并指定角色(發(fā)送者/接收者)。調(diào)用時(shí),參?
數(shù)dwFlags可指定套接字作為發(fā)送者(JL_SENDER_ONLY)、接收者(JL_RECEIVER_ONLY)?
或身兼兩者(JL_BOTH)。調(diào)用成功后會返回一個(gè)多播套接字,調(diào)用closesocket()函數(shù)?
關(guān)閉該套接字就離開了多播組,此時(shí)可以調(diào)用WSAJoinLeaf()函數(shù)再次加入多播組。注意?
,對多播組數(shù)據(jù)的接收和發(fā)送不能在該套接字上完成。?
7.向多播組發(fā)送數(shù)據(jù)?
調(diào)用sendto()函數(shù),可在指定的UDP套接字上向指定的多播組發(fā)送多播數(shù)據(jù)。調(diào)用時(shí),參?
數(shù)to應(yīng)指向多播組的IP地址。值得注意的是,若一個(gè)應(yīng)用程序只是打算給多播組發(fā)送數(shù)?
據(jù),便不必加入一個(gè)多播組。?
8.等待事件?
調(diào)用WSAAsyncSelect()函數(shù),使套接字置于非阻塞模式,這時(shí)應(yīng)用程序就可在該套接字?
上接收以Windows消息為基礎(chǔ)的網(wǎng)絡(luò)事件通知。例如,若參數(shù)lEvent值為FD_READ,則應(yīng)?
用程序可在套接字上接收到“數(shù)據(jù)正等待被讀入”的通知。?
9.從多播組接收數(shù)據(jù)?
調(diào)用recvfrom函數(shù),可在指定的UDP套接字上讀取輸入數(shù)據(jù)。多播通信中數(shù)據(jù)的發(fā)送與接?
收一般采用同一個(gè)端口,因此其發(fā)送套接字和接收套接字是一樣的。?
10.關(guān)閉套接字,釋放Winsock資源。?
在多播通信結(jié)束后,先調(diào)用closesocket()函數(shù)關(guān)閉多播套接字和UDP套接字,然后調(diào)用?
WSACleanup()函數(shù)結(jié)束對Windows Sockets DLL的使用。?
三、應(yīng)用實(shí)例?
為了說明IP多播技術(shù)的應(yīng)用方法,本人在Visual C++.NET環(huán)境下設(shè)計(jì)了一個(gè)簡單的基于?
Windows Socket 2的IP多播應(yīng)用程序,通過該例子讀者可以掌握IP多播應(yīng)用程序設(shè)計(jì)的?
一般方法。該程序的具體設(shè)計(jì)方法如下:?
1.在Visual Studio.NET中建立一個(gè)基于對話框的MFC項(xiàng)目CMulticastSocket。注意在“?
高級功能”設(shè)置中不要選擇“Windows套接字”,這是因?yàn)镸FC只支持Windows Socket 1?
而不支持Windows Socket 2。為了能使用Winsock 2 API編程,在程序中應(yīng)包含“winso?
ck2.h”頭文件,并在項(xiàng)目中加入ws2_32.lib的靜態(tài)庫,該靜態(tài)庫應(yīng)設(shè)置在項(xiàng)目屬性的“?
鏈接器”\“輸入”\“附加依賴項(xiàng)”中。?
2.在對話框(類名CCMulticastSocketDlg)資源中,設(shè)置它的Caption為“WinSock 2多?
播應(yīng)用程序”,并添加以下控件:?
靜態(tài)文本:Caption為“接收到的信息:”;?
編輯框:ID為IDC_RECEIVE_EDIT,Read Only、Auto Vscroll、Vertical Scroll和Mult?
iline屬性值都為True?
靜態(tài)文本:Caption為“發(fā)送的信息:”?
編輯框:ID為IDC_SEND_EDIT?
第一個(gè)按鈕:Caption為“加入多播組(&J)”,ID為IDC_JOIN_BUTTON?
第二個(gè)按鈕:Caption為“多播發(fā)送(&S)”,ID為IDC_SEND_BUTTON?
第三個(gè)按鈕:Caption為“離開多播組(&L)”,ID為IDC_LEAVE_BUTTON?
第四個(gè)按鈕:Caption為“退出(&Q)”,ID為IDC_QUIT_BUTTON?
為兩個(gè)編輯框分別添加相關(guān)聯(lián)的CString類型的變量m_SendMessage和m_ReceiveMessage?
;為四個(gè)按鈕添加相應(yīng)的消息處理函數(shù);為對話框添加定時(shí)器消息(用于定時(shí)顯示接收?
到的消息)及其消息處理函數(shù)。?
3.添加一個(gè)新的對話框資源,設(shè)置它的Caption為“加入多播組”,保留默認(rèn)的兩個(gè)按?
鈕控件,同時(shí)添加添加以下控件:?
靜態(tài)文本:Caption為“IP多播組地址:”?
編輯框:ID為IDC_IPADDRESS_EDIT?
靜態(tài)文本:Caption為“IP多播端口:”?
編輯框:ID為IDC_PORT_EDIT?
靜態(tài)文本:Caption為“生存時(shí)間:”?
編輯框:ID為IDC_TTL_EDIT?
復(fù)選框:Caption為“多播返回:”,ID為IDC_LOOPBACK_CHECK,Left Text屬性值為Tr?
ue。?
為該對話框添加新的類CJoinGroupDlg,它的基類為CDialog,然后為該對話框中的三個(gè)?
編輯框分別添加相關(guān)聯(lián)的變量,即CSting m_IPAddress、UINT m_nPort、UINT m_nTTL;?
為復(fù)選框添加相關(guān)聯(lián)的BOOL類型的變量m_Loopback。?
4.在CMulticastSocketDlg.h文件的前面添加CJoinGroupDlg的頭文件:#include “Jo?
inGroupDlg.h”,并在CCMulticastSocketDlg類中添加了一個(gè)CJoinGroupDlg類實(shí)例對象?
m_JoinDlg。?
5.為了能在對話框中接收網(wǎng)絡(luò)事件通知,應(yīng)增加一個(gè)用戶自定義的消息及消息處理函數(shù)?
,具體實(shí)現(xiàn)方法如下:在CMulticastSocketDlg.h文件的前面自定義消息:#define WM_?
SOCK_MSG(WM_USER+166),并在afx_msg塊中說明消息處理函數(shù):afx_msg LRESULT OnSo?
cketMsg (WPARAM wParam,LPARAM lParam);在CMulticastSocketDlg.cpp文件中的消息?
映射塊中,使用ON_MESSAGE (WM_SOCK_MSG,OnSocketMsg)宏指令將消息映射到消息處理?
函數(shù)中,并具體實(shí)現(xiàn)消息處理函數(shù):LRESULT CCMulticastSocketDlg:: OnSocketMsg(W?
PARAM wParam,LPARAM lParam){…}。?
該程序的主要代碼可參見程序清單,相關(guān)函數(shù)的詳細(xì)說明可參看Microsoft MSDN幫助系?
統(tǒng)。為了節(jié)省篇幅,程序中省略了部分自動(dòng)生成的和用于錯(cuò)誤處理的代碼。?
程序清單:?
// CMulticastSocketDlg.cpp : 實(shí)現(xiàn)文件?
#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; //分別指向本地、多播組和數(shù)據(jù)來源的IP地址與端口?
??
int Fromlen;?
char ReceiveBuf[32000]; //接收緩沖區(qū)?
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); //設(shè)置定時(shí)器?
Fromlen=sizeof(From);?
bDataReceived=TRUE;?
bJoin=FALSE;?
return TRUE; // 除非設(shè)置了控件的焦點(diǎn),否則返回 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套接字動(dòng)態(tài)鏈接庫,MB_OK");?
return;?
}?
if (LOBYTE(wsaData.wVersion) !=2 || HIBYTE(wsaData.wVersion) !=2){?
AfxMessageBox("WinSock DLL不支持2.0版本,MB_OK");?
WSACleanup( );?
return;?
}?
//創(chuàng)建一個(gè)套接字?
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; //設(shè)置套接字選項(xiàng),使套接字為可重用端口地址?
setsockopt(Sock,SOL_SOCKET,SO_REUSEADDR,(char*)&bFlag,sizeof(bFlag));?
//將套接字綁定到用戶指定端口及默認(rèn)的接口?
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));?
//設(shè)置多播數(shù)據(jù)報(bào)傳播范圍(生存時(shí)間TTL)?
WSAIoctl(Sock,SIO_MULTICAST_SCOPE,&m_JoinDlg.m_nTTL,sizeof(int),?
NULL,0,&cbRet,NULL,NULL);?
//設(shè)置多播返回(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);?
//加入到指定的多播組,并指定為既作為發(fā)送者又作為接收者(JL_BOTH)?
SockM=WSAJoinLeaf(Sock,(sockaddr*)&Remote,sizeof(Remote),?
NULL,NULL,NULL,NULL,JL_BOTH);?
WSAAsyncSelect(Sock,m_hWnd,WM_SOCK_MSG,FD_READ); //注冊網(wǎng)絡(luò)消息及其網(wǎng)絡(luò)事件?
bJoin=TRUE;?
}?
}?
void CCMulticastSocketDlg::OnBnClickedSendButton() //多播發(fā)送?
{?
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) //定時(shí)器處理函數(shù),實(shí)現(xiàn)接收?
信息的定時(shí)更新?
{?
if(bDataReceived)?
{?
m_ReceiveMessage+=ReceiveBuf;?
m_ReceiveMessage+="\r\n";?
bDataReceived=FALSE;?
UpdateData(FALSE);?
}?
CDialog::OnTimer(nIDEvent);?
}?
LRESULT CCMulticastSocketDlg::OnSocketMsg(WPARAM wParam,LPARAM lParam)?
{?
//檢索網(wǎng)絡(luò)事件?
switch(WSAGETSELECTEVENT(lParam)){?
case FD_READ:?
recvfrom(Sock,ReceiveBuf,32000,0,(sockaddr *)&From,&Fromlen);?
bDataReceived=TRUE; //設(shè)置已接收到一條信息標(biāo)志?
break;?
}?
return TRUE;?
}?
轉(zhuǎn)載于:https://www.cnblogs.com/huty/p/8517725.html
總結(jié)
以上是生活随笔為你收集整理的【miscellaneous】IP多播技术及其编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 69道Spring面试题和答案
- 下一篇: Mac平台下Opencv开发环境搭建