多播_2

设计报文广播的最初目的是用于资源发送和减少数据交互量。但事实上,由于报文广播时,同一网段内的所有主机,无论有没有参与广播应用,都必须完成对数据报的处理。被广播的UDP报文会被接收主机的系统协议栈逐层处理,知道传输层将其交付监听相应端口的应用进程或者丢弃。因此,频繁的大数据量的报文广播会严重影响网络上其他主机的正常运行。而多播方式在具有广播的优点同时,很好的解决了这个问题。

 

一个简单的多播库:

  1. //*************MCastLib.h***************// 
  2. #ifndef _MCASTLIB_H_ 
  3. #define _MCASTLIB_H_ 
  4.  
  5. #include<winsock2.h> 
  6. #include<ws2tcpip.h> 
  7.  
  8. #ifdef __cplusplus 
  9. extern "C" { 
  10. #endif 
  11.  
  12. int mc_join(SOCKET s,struct in_addr *mcaddr,struct in_addr *local_if); 
  13. int mc_setIF(SOCKET s,const DWORD local_out_if); 
  14. int mc_getIF(SOCKET s,DWORD *local_out_if); 
  15. int mc_setTTL(SOCKET s,const DWORD ttl); 
  16. int mc_getTTL(SOCKET s,DWORD *ttl); 
  17. int mc_setLoop(SOCKET s,const BOOL flag); 
  18. int mc_getLoop(SOCKET s,BOOL *flag); 
  19. int mc_leave(SOCKET s,struct in_addr *mcaddr,struct in_addr *local_if); 
  20.  
  21. #ifdef __cplusplus 
  22. #endif 
  23. #endif 

 

  1. //************************MCastLib.cpp*****************// 
  2. #include "MCastLib.h" 
  3. //本地接口local_if加入多播组mcaddr 
  4. int mc_join(SOCKET s,struct in_addr *mcaddr,struct in_addr *local_if) 
  5.     struct ip_mreq mreq; 
  6.     memcpy(&(mreq.imr_interface),local_if,sizeof(struct in_addr)); 
  7.     memcpy(&(mreq.imr_multiaddr),mcaddr,sizeof(struct in_addr)); 
  8.     return (setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mreq,sizeof(mreq))); 
  9. //为多播报文设置外出接口 
  10. int mc_setIF(SOCKET s,const DWORD local_out_if) 
  11.     return (setsockopt(s,IPPROTO_IP,IP_MULTICAST_IF,(char*)&local_out_if,sizeof(local_out_if))); 
  12. //获取多播报文的外出接口 
  13. int mc_getIF(SOCKET s,DWORD *local_out_if) 
  14.     int len = sizeof(DWORD); 
  15.     return (getsockopt(s,IPPROTO_IP,IP_MULTICAST_IF,(char*)local_out_if,&len)); 
  16. //设置外出多播报文的ttl值,默认为1 
  17. int mc_setTTL(SOCKET s,const DWORD ttl) 
  18.     return (setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,(char*)&ttl,sizeof(ttl))); 
  19. //获取外出多播报文的ttl值 
  20. int mc_getTTL(SOCKET s,DWORD *ttl) 
  21.     int len = sizeof(DWORD); 
  22.     return (getsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,(char*)ttl,&len)); 
  23. //启用或禁止多播报文回环 
  24. int mc_setLoop(SOCKET s,const BOOL flag) 
  25.     return (setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)&flag,sizeof(flag))); 
  26. //获取本地多播回环状态 
  27. int mc_getLoop(SOCKET s,BOOL *flag) 
  28.     int len = sizeof(BOOL); 
  29.     return (getsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)flag,&len)); 
  30. //本地接口local_if离开多播组mcaddr 
  31. int mc_leave(SOCKET s,struct in_addr *mcaddr,struct in_addr *local_if) 
  32.     struct ip_mreq mreq; 
  33.     memcpy(&(mreq.imr_interface),local_if,sizeof(struct in_addr)); 
  34.     memcpy(&(mreq.imr_multiaddr),mcaddr,sizeof(struct in_addr)); 
  35.     return (setsockopt(s,IPPROTO_IP,IP_DROP_MEMBERSHIP,(char*)&mreq,sizeof(mreq))); 

 

接收多播数据

  1. SOCKADDR_IN local; 
  2. memset(&local,0,sizeof(SOCKADDR_IN)); 
  3. local.sin_family=AF_INET; 
  4. local.sin_port=htons(5050); 
  5. local.sin_addr.s_addr=inet_addr("202.119.9.199"); 
  6. bind(sock,(SOCKADDR*)&local,sizeof(SOCKADDR_IN)); 
  7. struct in_addr mcaddr; 
  8. //202.119.9.199加入多播组226.1.2.3 
  9. mcaddr.s_addr=inet_addr("226.1.2.3"); 
  10. mc_join(sock,&mcaddr,&(local.sin_addr)); 
  11.  
  12. //接收数据 
  13. char buf[65]; 
  14. while(TRUE) 
  15.     memset(buf,0,65); 
  16.     recvfrom(sock,buf,65,0,NULL,NULL); 

上述代码使套接字加入多播组226.1.2.3,并接受发往该组的数据。当调用mc_join函数时,内核会自动向该组发送一个“IGMP v2 Memebership Report”报文,该报文会被组内的所有主机及路由器接收。

在套接字关闭时,无论有没有显示的调用mc_leave函数,进程都会离开多播组。

 

发送多播数据

  1. SOCKET sock = socket(AF_INET,SOCK_DGRAM,0); 
  2. //获取默认的多播报文TTL值和回环状态 
  3. DWORD ttl; 
  4. BOOL loop; 
  5. mc_getTTL(sock,&ttl); 
  6. mc_getLoop(sock,&loop); 
  7. printf("Multicast default: TTL=%d, LoopBack=%d\n",ttl,loop); 
  8. //设置多播TTL值为219 
  9. ttl=219; 
  10. mc_setTTL(sock,ttl); 
  11. //想多播组发送数据 
  12. SOCKADDR_IN to; 
  13. memset(&to,0,sizeof(SOCKADDR_IN)); 
  14. to.sin_family=AF_INET; 
  15. to.sin_port=htons(9999); 
  16. to.sin_addr.s_addr=inet_addr("226.1.2.3"); 
  17. char *buf="hello!"
  18. int res = sendto(sock,buf,6,0,(SOCKADDR*)&to,sizeof(to)); 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章