zoukankan      html  css  js  c++  java
  • 多播_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
    ",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)); 
    
    
    
     
  • 相关阅读:
    thinkphp SAE
    thinkphp rpc
    thinkphp REST
    thinkphp 图形处理
    thinkphp 验证码
    thinkphp 文件上传
    thinkphp 数据分页
    thinkphp 多语言支持
    thinkphp cookie支持
    thinkphp session支持
  • 原文地址:https://www.cnblogs.com/profession/p/4464436.html
Copyright © 2011-2022 走看看