多播_1
IPPROTO_IP 1.IP_HDRINCL,布尔型,仅适用于原始套接字(SOCK_RAW) 如果应用程序希望接收IP层及IP层以上的所有数据或者自行组装包含IP层在内的报文,那么可以设置该选项为TRUE。 2.IP_ADD_MEMBERSHIP,struct ip_mreq结构,用于加入多播组 该选项用于将指定网络接口上的套接字加入IP多播组,此套接字必须是AF_INET地址族并且类型为SOCK_DGRAM。 struct ip_mreg{ struct in_addr imr_multiaddr;/*IP multicast address of group*/ struct in_addr imr_interface;/*local IP address of interface*/ }; 其中imr_multiaddr对应于打算加入的多播组IPv4地址;而imr_interface是本地接口的IP地址,也可以设置为INADDR_ANY,表明选择的是默认接口。 3.IP_DROP_MEMBERSHIP,struct ip_mreq结构,由于退出多播组,该选项的使用与IP_ADD_MEMBERSHIP类似。 4.IP_MULTICAST_IF,BOTH,DWORD类型,设置/读取多播的本地接口。 IP_MULTICAST_IF选项用于设置或读取本地接口,在设置了本地的多播外出接口后,本地机器以后发出的任何多播数据都会经由它传送出去,该选项多用于多穴主机。 5.IP_MULTICAST_LOOP,BOTH,布尔类型,用于启用或禁止多播报文回环。 在默认情况下,当发送IP多播数据时,如果发生套接字本身也属于该多播组,那么数据会原封不动的返回一份至套接字---回环(loopback)。若将该选项设为FALSE,发出的任何数据对都不会投递至套接字的进入数据队列中。 6.IP_MULTICAST_TTL,BOTH,DWORD类型,设置/读取套接字上IP多播的TTL值。 在默认情况下,多播数据报采用的TTL值为1,IP_MULTICAST_TTL选项可用于读取或设置该值。多播TTL值的大小影响到多播数据的传播范围。只有在有效范围内的组成员才会收到数据。
设计报文广播的最初目的是用于资源发送和减少数据交互量。但事实上,由于报文广播时,同一网段内的所有主机,无论有没有参与广播应用,都必须完成对数据报的处理。被广播的UDP报文会被接收主机的系统协议栈逐层处理,知道传输层将其交付监听相应端口的应用进程或者丢弃。因此,频繁的大数据量的报文广播会严重影响网络上其他主机的正常运行。而多播方式在具有广播的优点同时,很好的解决了这个问题。 一个简单的多播库: //*************MCastLib.h***************// #ifndef _MCASTLIB_H_ #define _MCASTLIB_H_ #include<winsock2.h> #include<ws2tcpip.h> #ifdef __cplusplus extern "C" { #endif int mc_join(SOCKET s,struct in_addr *mcaddr,struct in_addr *local_if); int mc_setIF(SOCKET s,const DWORD local_out_if); int mc_getIF(SOCKET s,DWORD *local_out_if); int mc_setTTL(SOCKET s,const DWORD ttl); int mc_getTTL(SOCKET s,DWORD *ttl); int mc_setLoop(SOCKET s,const BOOL flag); int mc_getLoop(SOCKET s,BOOL *flag); int mc_leave(SOCKET s,struct in_addr *mcaddr,struct in_addr *local_if); #ifdef __cplusplus } #endif #endif //************************MCastLib.cpp*****************// #include "MCastLib.h" //本地接口local_if加入多播组mcaddr int mc_join(SOCKET s,struct in_addr *mcaddr,struct in_addr *local_if) { struct ip_mreq mreq; memcpy(&(mreq.imr_interface),local_if,sizeof(struct in_addr)); memcpy(&(mreq.imr_multiaddr),mcaddr,sizeof(struct in_addr)); return (setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mreq,sizeof(mreq))); } //为多播报文设置外出接口 int mc_setIF(SOCKET s,const DWORD local_out_if) { return (setsockopt(s,IPPROTO_IP,IP_MULTICAST_IF,(char*)&local_out_if,sizeof(local_out_if))); } //获取多播报文的外出接口 int mc_getIF(SOCKET s,DWORD *local_out_if) { int len = sizeof(DWORD); return (getsockopt(s,IPPROTO_IP,IP_MULTICAST_IF,(char*)local_out_if,&len)); } //设置外出多播报文的ttl值,默认为1 int mc_setTTL(SOCKET s,const DWORD ttl) { return (setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,(char*)&ttl,sizeof(ttl))); } //获取外出多播报文的ttl值 int mc_getTTL(SOCKET s,DWORD *ttl) { int len = sizeof(DWORD); return (getsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,(char*)ttl,&len)); } //启用或禁止多播报文回环 int mc_setLoop(SOCKET s,const BOOL flag) { return (setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)&flag,sizeof(flag))); } //获取本地多播回环状态 int mc_getLoop(SOCKET s,BOOL *flag) { int len = sizeof(BOOL); return (getsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)flag,&len)); } //本地接口local_if离开多播组mcaddr int mc_leave(SOCKET s,struct in_addr *mcaddr,struct in_addr *local_if) { struct ip_mreq mreq; memcpy(&(mreq.imr_interface),local_if,sizeof(struct in_addr)); memcpy(&(mreq.imr_multiaddr),mcaddr,sizeof(struct in_addr)); return (setsockopt(s,IPPROTO_IP,IP_DROP_MEMBERSHIP,(char*)&mreq,sizeof(mreq))); } 接收多播数据 SOCKADDR_IN local; memset(&local,0,sizeof(SOCKADDR_IN)); local.sin_family=AF_INET; local.sin_port=htons(5050); local.sin_addr.s_addr=inet_addr("202.119.9.199"); bind(sock,(SOCKADDR*)&local,sizeof(SOCKADDR_IN)); struct in_addr mcaddr; //202.119.9.199加入多播组226.1.2.3 mcaddr.s_addr=inet_addr("226.1.2.3"); mc_join(sock,&mcaddr,&(local.sin_addr)); //接收数据 char buf[65]; while(TRUE) { memset(buf,0,65); recvfrom(sock,buf,65,0,NULL,NULL); } 上述代码使套接字加入多播组226.1.2.3,并接受发往该组的数据。当调用mc_join函数时,内核会自动向该组发送一个“IGMP v2 Memebership Report”报文,该报文会被组内的所有主机及路由器接收。 在套接字关闭时,无论有没有显示的调用mc_leave函数,进程都会离开多播组。 发送多播数据 SOCKET sock = socket(AF_INET,SOCK_DGRAM,0); //获取默认的多播报文TTL值和回环状态 DWORD ttl; BOOL loop; mc_getTTL(sock,&ttl); mc_getLoop(sock,&loop); printf("Multicast default: TTL=%d, LoopBack=%d\n",ttl,loop); //设置多播TTL值为219 ttl=219; mc_setTTL(sock,ttl); //想多播组发送数据 SOCKADDR_IN to; memset(&to,0,sizeof(SOCKADDR_IN)); to.sin_family=AF_INET; to.sin_port=htons(9999); to.sin_addr.s_addr=inet_addr("226.1.2.3"); char *buf="hello!"; int res = sendto(sock,buf,6,0,(SOCKADDR*)&to,sizeof(to));
posted on 2015-04-28 23:37 strangeman 阅读(412) 评论(0) 编辑 收藏 举报