多播_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)); 

 

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