• linux 多播


    1.概念

    单播是用于两个主机之间传送数据,广播是一个主机对局域网内的所有主机发送数据。而多播,又称为组播,它是对一组特定的主机通信。将网络上同一类型 业务逻辑上分组,只和组内的成员通信,其它主机没有加入组则不能通信。与单播相同的是,组播允许在Internet上通信,而广播只是同一局域网内的主机 通信。组播地址是特定的,D类地址用于组播,即244.0.0.0到239.255.255.255. 并划分为局部连接多播地址,预留多播地址和管理权限多播地址3类。

    2. 多播套接字设置

    可用setsockopt或getsockopt设置或得到多播选项. 常用的多播选项如下所示:

    IP_MULTICAST_TTL    设置多播的TTL值

    IP_MULTICAST_IF      获取或设置多播接口

    IP_MULTICAST_LOOP   禁止多播数据回送到本地loop接口

    IP_ADD_MEMBERSHIP   将指定的接口加入多播

    IP_DROP_MEMBERSHIP  退出多播组

    struct ip_mreq{
      struct in_addr imn_multicastaddr;//多播组地址
      struct in_addr imr_interface;//加入的接口的IP地址
    }

    /*PROTO_IP-选项所在的协议层
    *IP_MULTICAST_TTL-选项名
    *&ttl-设置的内存缓冲区
    *sizeof(ttl)-设置的内存缓冲区长度*/

    int ttl=255;
    setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl));//设置跳数


    struct in_addr in;
    setsockopt(s,IPPROTO_IP,IP_MUTLICAST_IF,&in,sizeof(in));//设置组播接口

    int yes=1;
    setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&yes,sizeof(yes));//设置数据回送到本地回环接口

    struct ip_mreq addreq;
    setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,&req,sizeof(req));//加入组播组

    struct ip_mreq dropreq;
    setsockopt(s,IPPROTO_IP,IP_DROP_MEMBERSHIP,&dropreq,sizeof(dropreq));//离开组播组

    3. 多播程序的设计流程

    (1)建立socket

    (2)设置TTL值 IP_MULTICAST_TTL

    (3)设置是否允许本地回环 IP_MULTICAST_LOOP

    (4)加入多播组 IP_ADD_MEMBERSHIP

    (5)发送数据 send

    (6)接收数据 recv

    (7)退出多播组 IP_DROP_MEMBERSHIP

    4、多播服务器端

     1 //服务器实现向多播组发送数据
     2 #define MCAST_PORT 8888
     3 #define MCAST_ADDR "224.0.0.88"
     4 int main(int argc,char*argv[]){
     5  int ret;
     6  int s;
     7  int i=1;
     8  struct sockaddr_in Multi_addr;//多播地址
     9  struct sockaddr_in client_addr;
    10  s=socket(AF_INET,SOCK_DGRAM,0);//建立数据报套接字
    11  if(s<0){
    12    perror("socket error");
    13    return -1;
    14  }
    15  Multi_addr.sin_family=AF_INET;
    16  Multi_addr.sin_port=htons(MCAST_PORT);//多播端口
    17  Multi_addr.sin_addr.s_addr=inet_addr(MCAST_ADDR);//多播地址
    18 //向多播组发送数据
    19 char buffer[1024];
    20  for(;;){
    21   memset(buffer,0,sizeof(buffer));
    22   sprintf(buffer,"%d",i);
    23   int size=sendto(s,buffer,strlen(buffer),0,(struct sockaddr*)&Multi_addr,sizeof(Multi_addr));
    24   if(size<0){
    25     perror("sendto error");
    26   }
    27   sleep(1);
    28   i++;
    29   memset(buffer,0,sizeof(buffer));
    30   int len=sizeof(client_addr);
    31   size=recvfrom(s,buffer,1024,0,(struct sockaddr*)&client_addr,&len);
    32   write(1,buffer,size);
    33 }
    34 close(s);
    35 }
    
    

    5、客户端代码

     1 加入多播组的主机:
     2 #include <sys/types.h>
     3 #include <sys/socket.h>
     4 #include <string.h>
     5 #include <stdio.h>
     6 #include <stdlib.h>
     7 #include <netinet/in.h>
     8 //多播的客户端程序
     9 #define PORT 8888
    10 #define MCAST "224.0.0.88"
    11 int main(int argc,char*argv[]){
    12   int s;
    13   int ret;
    14   int size;
    15   int ttl=10;//如果转发的次数等于10,则不再转发
    16   int loop=0;
    17   int times=0;
    18   char buffer[1024];
    19   struct sockaddr_in localaddr,fromaddr;//多播地址结构
    20  //建立套接字
    21   s=socket(AF_INET,SOCK_DGRAM,0);
    22   if(s<0){
    23    perror("socket error");
    24     return -1;
    25   }
    26   //多播的地址结构
    27   localaddr.sin_family=AF_INET;
    28   localaddr.sin_port=htons(PORT);//多播端口号
    29   localaddr.sin_addr.s_addr=htonl(INADDR_ANY);//接收任意地址发送的数据
    30  //绑定地址结构到套接字
    31  ret=bind(s,(struct sockaddr*)&localaddr,sizeof(localaddr));//客户端需要绑定端口,用来接收服务器的数据,得指定接收端口,因为数据先从服务器发送过来的
    32 if(ret<0){
    33   perror("bind error");
    34   return -1;
    35 }
    36  //设置多播的TTL值
    37  if(setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl))<0){
    38     perror("IP_MULTICAST_TTL");
    39     return -1;
    40   }
    41 
    42 //设置数据是否发送到本地回环接口
    43 if(setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop))<0){
    44   perror("IP_MULTICAST_LOOP");
    45   return -1;
    46  }
    47 //客户端加入多播组
    48  struct ip_mreq mreq;
    49  mreq.imr_multiaddr.s_addr=inet_addr(MCAST);//多播组的IP
    50  mreq.imr_interface.s_addr=htonl(INADDR_ANY);//本机的默认接口IP
    51 if(setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq))<0){
    52   perror("IP_ADD_MEMBERSHIP");
    53   return -1;
    54 }
    55 //循环接收多播组的消息,5次退出
    56 for(times=0;times<20;times++){
    57   int len=sizeof(fromaddr);
    58   memset(buffer,0,sizeof(buffer));
    59   size=recvfrom(s,buffer,1024,0,(struct sockaddr*)&fromaddr,&len);
    60  if(size<0){
    61    perror("recvfrom ");
    62   return -1;
    63  }
    64  printf("receive message:%s
    ",buffer);
    65  printf("Port is:%d
    ",fromaddr.sin_port);
    66  size=sendto(s,"OK",2,0,(struct sockaddr*)&fromaddr,sizeof(fromaddr));//向服务器发送数据,向服务器指定的IP与端口发送数据
    67 }
    68 
    69 //离开多播组
    70 ret=setsockopt(s,IPPROTO_IP,IP_DROP_MEMBERSHIP,&mreq,sizeof(mreq));
    71 if(ret<0){
    72   perror("IP_DROP_MEMBERSHIP");
    73   return -1;
    74 }
    75 close(s);
    76 return 0;
    77 
    78 } 
  • 相关阅读:
    第一个Django demo
    内建函数
    Git积累
    区间dp
    【Spring】Spring AOP详解(转载)
    【git】git 常用命令(含删除文件)
    【idea】idea如何在maven工程中引入jar包
    【Java】Scanner类nextInt后使用nextLine无法读取输入
    【Java_Eclipse】Eclipse插件如何卸载?
    【MySQL】MySQL5.7等以上版本在Windows上的配置
  • 原文地址:https://www.cnblogs.com/meizixiong/p/3208958.html
Copyright © 2020-2023  润新知