网络通信中组播的实现

  • 格式:pdf
  • 大小:138.02 KB
  • 文档页数:3

计算机与网络创新生活 通信论坛 

网络通信中组播的实现 

蔡文斋王录选 

(中国电子科技集团公司第39研究所 陕西 西安710065) 

【摘要】组播是网络通信经常使用的重要通信方式,航天测控工程中尤其常用,测控中心从各个分机读状态信息,然后 

给几个确定的分机发相应的指令,组播编程是网络编程的难点。本文展示了Socket1.1和Socket2 2下的网络组播编程的要点, 

示的是作者开发的通用网络调试器的部分内容,在此基础上设计的网络调试器已ii ̄_r-程实践多次检验。 【关键词】TCP/IP协议 UDP协议组播线程事件 网络编程 

1引言 

组播是intemet上较特殊的一类应用.国际组织标准化规 定组播地址为从224.0.0 0到239.255.255.255,组播执行的是 

UDP协议,在Windows32环境下,实现组播分2种形式,一种 形式为Socket1.1,另一种形式为Socket2.2,在2种规范的 

Win32 API函数差异较大,实现的形式也是不同的。 

2组播初始化函数 

作者使用Delplli7.0开发工具编写了一个通用网络调试 

器,组播是其中的一部分,因组播的特殊性,实现起来并不轻 松。组播一般没有现成的组件支持,全部使用Win32^_pi实 

现,参考Vc++的有关样例后发现Delplli给我们提供的API 接口与原MSDN中的数据定义文件稍有不同,需要我们自己 改造有关的网络数据结构后才能使用。作者写的这个网络调 

试器设计目标为读地址与写地址允许用户任意配置,比如从 

一台计算机上实现,读组播地址为224.0.0 1—224 0.0.4,写组 播地址为:230.2.3 1—230.2.3.6,也就是说从4台计算机上读信 息,写给6台计算机另外的信息。文中略去了delphi环境下地 址组装的实现,仅给出了关键的Socket编程部分。作者写了2 

个初始化函数,分别对应Socket1.1和Socket2.2,使用 Tstringlist存一组地址。 编制了两个小函数GetlPAd&ess()和SplitslpAd- 

dressTolntcger(): GetlPAddress读取本机IP地址: SplitslpAddressTolnteger用于IP地址各字段分离出供初 

始化函数调用。 例程: Type//数据结构定义 

ip mreq=record 

定稿日期:2007-03—17 imr_multiaddr:in_addr;// IP multicast address of group 

imr_interface:in_addr; // local IP address of inte ̄ end; 

vat mreq:ip_mreq; Sock:TSOCKET; 

LocaL_Address:sockaddr in; SendRemote_Address:sockaddr in; Socket1.1实现 //初始化LocallPAddress:=GetlPAddress: 

SplitslpAddressTolnteger(LocallPAddress, LocalAddress2, 41 

LocalAddressI, 

LocalAddress3,LocalAddress4);//将IP号转换为数值 

status: WSAStartup(MAg ̄WORD UDP协议版本号 

sock :=socket (1,1),wsdata);//定制 

(PF_INET,SOCK__DGRAM,IPPRO- 

TO_UDP);//定制通信协议 

local_address.sin_family:=PF INET; 

local_address.sin_port: htons(LocalPort); 

local_address.sin_addr.S_un_b.s_bl:=Chr(LocalAddressI); 

local_address.sin_addr.S_un b s_b2:=Chr(LocalAddress2); 

.S_un_b.s_b3:=Chr(LocalAddress3); 

.S_un_b.s b4:=Chr(LocalAddress4); BindStatus:=bind(sock,local_address,sizeof0local address)); //……--一…一一一… //Fill group address, 

Read Remo ̄WORK GROUP NUMBER TempReadlpAd- 

dress: ReadRemoteGroupStringList.Strings [i】; SplitslpAd dressTolnteger(TempRe ̄IpAddress。ReadRemoteGroupAd- 

dress1,ReadRemoteGroupAddress2,eadRemoteGroupAddress3, 

ReadRemoteGroupAddress4); //Remo ̄Read group address mreq.imr multiaddr.S-.uIl-b 

s.b1:= Address1); 

mreq.imr multiaddr.S un b.s_b2: Chr(ReadRemote- 

2007年第8期<计算机与网络

》 维普资讯 http://www.cqvip.com 通信论坛 

● I●liT丽疆 .i.●l札lI啊l 硝l I _1丁 .R-49L:爿 三口已U 丽 Z=E j白 1一, 

GroupAddress2);//0;@nLoopBack,sizeof(nLoopBack),nil,0,@cblket,nil, <> 

mreq.imr_mulfiaddr.S_un_b.s_b3: =Chr(R.eadR.emote- so( ET ER R oR then beg.m for i: 0 tO J do begin Tem— GroupAddress3);110;plkeadlpAddres ̄=IkeadlLemoteGroupStringListStrin醐; 

mreq.imr_multiaddr.S_un_b.s_b4: Chr(Readl ̄emote— msAddr: Pch ̄(TempR.eadIpAddress): GroupAddress4);//0; Remote.s mi : AF_INET; 

mreq.imr jnter&ce.S_un_b.s—b1:=Chr(LocalAddress1);11 Remote.sin_addr.s_addr: inet__addr(msAddr); 

LOCAL IP address Remote.sin_port: htons([ ̄emotePort): 

mreq.imr jnte而ce.S_un_b.s_b2:=Chr(LocalAddress2); //加入到指定的多播组,并指定为既作为发送者又作为 

rm'eq.imr_interface.S un b.s_b3:=Chr(LocalAddress3); 接收者(JL__BoTH) 

mreq.imr_interface.S_un_b.s_b4:=Chr(LocalAddress4): SockM: WSAJoinLeaf(Sock,,Remote,sizeof(Remote), ioctlsocket(sock,FIONBIO,paraforblock);//完成地址绑定 nil,nil,nil,nilJL_BOTH); SetSockoptStatus0:=0; WSAAsyncSelect(Sock。SocketHandle。WM_SOCK_MSG, 

SetSockoptStatus0:=setsockopt(sock,IPPILOTO_IP,IP AD FD_READ or FD_WtLITE or FD_CONNECT or FD_CLOSE 

D MEMBERSHIP, ̄mreq。//(char )&mreq,sizeof(rare,);// or FD_ACcEP 加入到指定的多播组<>SOCKET_EILILOtL then//注册网络消息及其网络事 

Socket2.2实现 件end。 

//初始化 

status:=WSAStartup(MAKEWORD(2・2),wsdata); 3组播数据接收 if status=0 then be咖 //创建一个套接字Sock:= 

wsAs。ck。 ( '_INET,SOcIr_DGRAM・IPPRoTo__UDP,nd・ 对socket1.1下的UDP组播而言,使用线程收。该线程一 0,(wsA_—FLAG_ovERLAPPED 0r ws^』LAG_MU】 I一 直在读网络口。同步机制由s。clcet接收函数保证。如果读不 PoINr_lC_—LE^ 0r wSA.FLAGJⅥU】 IPoINr_叫AF)) 到,该线程将处于自动等待状态;如果等到,读数据到缓冲区。 bFhg: tI1le;//设置套接字选项・使套接字为可重用端口 同时发读完成消息给前台。通知读已完成。 地址 //s。cket1.1下的uDP组播而言,使用接收线程接收,线 if。吣。d op (Sock,SOL_soa(ET,So』 us DR, 程代码省略。接收函数如下: @bFhg, 。f【b )<>soC髓T-ERRoR tllen b。giI1 s。cketstatus::re m (s。ck,Globa1Reads。clc衄 , 

…loc…a1.sm…_fa—mUy。_删NET /将套接字绑定到用户指定 1024,0㈣ P.addr / 变量返回网络读取地址,dw_ 端口及默认的接口 一 

loca1.sin_port:=htons(LocalPort); I对s。 2下的UDP组播而言,读机制是基于用户消 

loca1.sin_addr.s_addr:=htonI(INADDR,_ANY); //local address. 正IIIl ::PF INET; 息函数形态的,s。cke ・2的初始化wsA yTlcselect(s。cl【, 

//l0c d .s ::htons calP ; s。ck andl。’w_M_socK sG. 

1oca1.sin_addr.s lln b.s_-b1::Byte(L。c d出ess1);FDj AD。 H)-删TE 0r FD—CoNNEcT 0r 

loca1.siI1-addr.s lm b.s-b2::Byte(L。ca dress2); cLosE。 FD—AccE loca1.sin addr.s un b.s-1)3::byte 。ca1Address3); <>soa【ET.IERRoR定义了网络接收消息,我们需要自 l。caLsin_addr.s un b.s_ 4::byte caLAddress4); 己定义该消息,一旦网络口有东西来,该消息函数被自动调 

n1srrL::32: 用,读数据到缓冲区,同时发读完成消息给前台,通知读已完 ifbind(Sock,@l。cal,size。f Ooca1))<>SOCKET_EILILOtL 成。 

tllen be咖//设置多播返回(LOO ̄ACK),设置多播数据报 ‘读完成消息 

传播范围(生存时间rrL) 无论是那种形式的网络读取,只要从网络口读取到数据。 IF SAIoctl(sock,SIO MULTICAST_SCOPE, ̄msTTL, 后台线程或回调函数都会发用户消息到前台,该消息完成解