现在的位置: 首页 > 综合 > 正文

网络组播技术

2013年07月14日 ⁄ 综合 ⁄ 共 6658字 ⁄ 字号 评论关闭

多播的地址是特定的,D类地址用于多播。D类IP地址就是多播IP地址,即224.0.0.0至239.255.255.255之间的IP地址,并被划分为局部连接多播地址、预留多播地址和管理权限多播地址3类:


局部多播地址:在224.0.0.0~224.0.0.255之间,这是为路由协议和其他用途保留的地址,路由器并不转发属于此范围的IP包。

   预留多播地址:在224.0.1.0~238.255.255.255之间,可用于全球范围(如Internet)或网络协议。
   管理权限多播地址:在239.0.0.0~239.255.255.255之间,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制多播范围。

一、Linux上的实现

1.1 Linux下多播数据接收端的基本步骤:
   多播程序框架主要包含套接字初始化、设置多播超时时间、加入多播组、发送数据、接收数据以及从多播组中离开几个方面。其步骤如下:
(1)建立一个socket。
(2)然后设置多播的参数,例如超时时间TTL、本地回环许可LOOP等。
(3)加入多播组。
(4)发送和接收数据。
(5)从多播组离开。

  多播组的IP地址为224.0.0.88,端口为8888,当客户端接收到多播的数据后将打印出来。客户端只有在加入多播组后才能接受多播组的数据,因此多播接收端在接收多播组的数据之前需要先加入多播组,当接收完毕后要退出多播组。

/*    
*broadcast_client.c - 多播的客户端    
*/    
#define MCAST_PORT 8888;    
#define MCAST_ADDR "224.0.0.88"     /*一个局部连接多播地址,路由器不进行转发*/    
#define MCAST_INTERVAL 5                        /*发送间隔时间*/    
#define BUFF_SIZE 256                           /*接收缓冲区大小*/    
int main(int argc, char*argv[])    
{      
    int s;                                      /*套接字文件描述符*/    
    struct sockaddr_in local_addr;              /*本地地址*/    
    int err = -1;    
            
    s = socket(AF_INET, SOCK_DGRAM, 0);     /*建立套接字*/    
    if (s == -1)    
    {    
        perror("socket()");    
        return -1;    
    }      
            
                                                /*初始化地址*/    
    memset(&local_addr, 0, sizeof(local_addr));    
    local_addr.sin_family = AF_INET;    
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);    
    local_addr.sin_port = htons(MCAST_PORT);    
            
                                                /*绑定socket*/    
    err = bind(s,(struct sockaddr*)&local_addr, sizeof(local_addr)) ;    
    if(err < 0)    
    {    
        perror("bind()");    
        return -2;    
    }    
            
                                                /*设置回环许可*/    
    int loop = 1;    
    err = setsockopt(s,IPPROTO_IP, IP_MULTICAST_LOOP,&loop, sizeof(loop));    
    if(err < 0)    
    {    
        perror("setsockopt():IP_MULTICAST_LOOP");    
        return -3;    
    }    
            
    struct ip_mreq mreq;                                    /*加入广播组*/    
    mreq.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR); /*多播地址*/    
    mreq.imr_interface.s_addr = htonl(INADDR_ANY); /*网络接口为默认*/    
                                                        /*将本机加入广播组*/    
    err = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq, sizeof    
    (mreq));    
    if (err < 0)    
    {    
        perror("setsockopt():IP_ADD_MEMBERSHIP");    
        return -4;    
    }    
            
    int times = 0;    
    int addr_len = 0;    
    char buff[BUFF_SIZE];    
    int n = 0;    
                                        /*循环接收广播组的消息,5次后退出*/    
    for(times = 0;times<5;times++)    
    {    
        addr_len = sizeof(local_addr);    
        memset(buff, 0, BUFF_SIZE);                 /*清空接收缓冲区*/    
                                                    /*接收数据*/    
        n = recvfrom(s, buff, BUFF_SIZE, 0,(struct sockaddr*)&local_addr,    
        &addr_len);    
        if( n== -1)    
        {    
            perror("recvfrom()");    
        }    
                                                    /*打印信息*/    
        printf("Recv %dst message from server:%sn", times, buff);    
        sleep(MCAST_INTERVAL);    
    }    
            
                                                    /*退出广播组*/
    err = setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP,&mreq, sizeof    
    (mreq));    
                
    close(s);    
    return 0;    
}

//选项IP_ADD_MEMBERSHIP用于加入某个多播组,之后就可以向这个多播组发送数据或者从多播组接收数据。此选项的值为mreq结构,成员imn_multiaddr是需要加入的多播组IP地址,成员imr_interface是本机需要加入广播组的网络接口IP地址。

1.2 多播数据发送端

下面的例子持续向多播IP地址"224.0.0.88"的8888端口发送数据"BROADCAST TEST DATA",每发送一次间隔5s。 

/*    
*broadcast_server.c - 多播服务程序    
*/    
#define MCAST_PORT 8888;    
#define MCAST_ADDR "224.0.0.88"/    /*一个局部连接多播地址,路由器不进行转发*/    
#define MCAST_DATA "BROADCAST TEST DATA"            /*多播发送的数据*    
#define MCAST_INTERVAL 5                            /*发送间隔时间*/    
int main(int argc, char*argv)    
{    
    int s;    
    struct sockaddr_in mcast_addr;         
    s = socket(AF_INET, SOCK_DGRAM, 0);         /*建立套接字*/    
    if (s == -1)    
    {    
        perror("socket()");    
        return -1;    
    }    
            
    memset(&mcast_addr, 0, sizeof(mcast_addr));/*初始化IP多播地址为0*/    
    mcast_addr.sin_family = AF_INET;                /*设置协议族类行为AF*/    
    mcast_addr.sin_addr.s_addr = inet_addr(MCAST_ADDR);/*设置多播IP地址*/    
    mcast_addr.sin_port = htons(MCAST_PORT);        /*设置多播端口*/    
            
                                                    /*向多播地址发送数据*/    
    while(1) {    
        int n = sendto(s,                           /*套接字描述符*/    
                                    MCAST_DATA,     /*数据*/    
                                    sizeof(MCAST_DATA),    /*长度*/    
                                    0,    
                                    (struct sockaddr*)&mcast_addr,    
                                    sizeof(mcast_addr)) ;    
        if( n < 0)    
        {    
            perror("sendto()");    
            return -2;    
        }          
                
        sleep(MCAST_INTERVAL);                          /*等待一段时间*/
    }    
            
    return 0;    
}

 

二、android WIFI组播:

2.1. 打开权限

<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />

<uses-permission android:name="android.permission.INTERNET"/>

2.2 打开组播锁,默认时,移动设备为了省电是关闭的
WifiManager wifi = (WifiManager)getSystemService( Context.WIFI_SERVICE);
if(wifi != null)
{
MulticastLock mcLock = wifi.createMulticastLock("mylock");
mcLock
.acquire();
...

public class MulticastDemoActivity extends Activity { 
    
    MulticastLock multicastLock; 
    
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        
        allowMulticast(); 
        
        try { 
            NetUtil.findServerIpAddress(); 
        } catch (IOException e) { 
            throw new RuntimeException(e); 
        } 
        
        Log.d("multicast.demo", "find ip ok."); 
        
        multicastLock.release(); 
    } 
    
    private void allowMulticast(){ 
        WifiManager wifiManager=(WifiManager)getSystemService(Context.WIFI_SERVICE); 
        multicastLock=wifiManager.createMulticastLock("multicast.test"); 
        multicastLock.acquire(); 
    } 
}

使用组播发送报文和接收ip地址信息的工具类代码:

public class NetUtil { 
    
    private static final String TAG="Net.Utils"; 
    private static final int MULTICAST_PORT=5111; 
    private static final String GROUP_IP="224.5.0.7"; 
    private static byte[] sendData; 
    
    static{ 
        sendData=new byte[4]; 
        // 0xEE78F1FB 
        sendData[3] = (byte) 0xEE; 
        sendData[2] = (byte) 0×78; 
        sendData[1] = (byte) 0xF1; 
        sendData[0] = (byte) 0xFB; 
    } 
    
    public static String findServerIpAddress() throws IOException{ 
        String ip=null;

        MulticastSocket multicastSocket=new MulticastSocket(MULTICAST_PORT); 
        multicastSocket.setLoopbackMode(true); 
        InetAddress group = InetAddress.getByName(GROUP_IP); 
        multicastSocket.joinGroup(group); 
        
        DatagramPacket packet=new DatagramPacket(sendData, sendData.length,group,MULTICAST_PORT); 
        
        for(;;){ 
            multicastSocket.send(packet); 
            Log.d(TAG,">>>send packet ok"); 
            
            byte[] receiveData=new byte[256]; 
            packet=new DatagramPacket(receiveData, receiveData.length); 
            multicastSocket.receive(packet); 
            
            String packetIpAddress=packet.getAddress().toString(); 
            packetIpAddress=packetIpAddress.substring(1, packetIpAddress.length()); 
            Log.d(TAG,"packet ip address: "+packetIpAddress); 
            
            StringBuilder packetContent=new StringBuilder(); 
            for(int i=0;i<receiveData.length;i++){ 
                if(receiveData[i]==0){ 
                    break; 
                } 
                packetContent.append((char)receiveData[i]); 
            } 
            ip=packetContent.toString(); 
            Log.d(TAG,"packet content ip is: "+ip); 
            
            if(ip.equals(packetIpAddress)){ 
                Log.d(TAG,"find server ip address: "+ip); 
                break; 
            }else{ 
                Log.d(TAG,"not find server ip address, continue …"); 
                try { 
                    Thread.sleep(1000); 
                } catch (InterruptedException e) { 
                } 
            } 
        } 
        
        return ip; 
    } 
}

http://tech.ddvip.com/2013-05/1368542484195543.html

抱歉!评论已关闭.