组播

  1. 组播概念
    单播方式只能发给一个接收方。
    广播方式发给所有的主机。过多的广播会大量占用网络带宽,造成广播风暴,影响正常的通信。
    组播(又称为多播)是一种折中的方式。只有加入某个多播组的主机才能收到数据。
    多播方式既可以发给多个主机,又能避免象广播那样带来过多的负载(每台主机要到传输层才能判断广播包是否要处理)
  2. 组播地址段
    D类地址(组播地址)
    不分网络地址和主机地址,第1字节的前4位固定为1110
    224.0.0.1 – 239.255.255.255
  3. 代码流程
    发送者(send):
    创建套接字;
    填充组播网络信息结构体;
    发送消息

    接收者(recv):
    创建套接字;
    填充组播网络信心结构体;
    绑定IP和端口号;
    将接收者加入到多播组里面;

    1. 用到的结构体
      struct ip_mreq
      {
      /* IP multicast address of group. */
      struct in_addr imr_multiaddr; //组播地址,发送者地址

      /* Local IP address of interface. */
      struct in_addr imr_interface; //主机地址
      //INADDR_ANY 任意的主机地址
      };

    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(argv[1]);
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);

发送端(send)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//实现组播的发送

#define N 128

#define err_log(errmsg) do{perror(errmsg); exit(1);}while(0)

int main(int argc, const char *argv[])
{
    int sockfd;
    struct sockaddr_in groupcastaddr;
    char buf[N] = {};

    if(argc < 3)
    {
        fprintf(stderr, "Usage: %s broadcast-ip-port.\n", argv[0]);
    }

    //第一步:创建套接字
    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        err_log("fail to socket");
    }

    //第二步:填充组播信息结构体
    groupcastaddr.sin_family = AF_INET;
    groupcastaddr.sin_addr.s_addr = inet_addr(argv[1]);
    groupcastaddr.sin_port = htons(atoi(argv[2]));

    //第三步:发送数据
    while(1)
    {
        printf("groupcast__msg >>> ");

        fgets(buf, N, stdin);
        buf[strlen(buf) - 1] = '\0';

        if(sendto(sockfd, buf, N, 0, (struct sockaddr *)&groupcastaddr, sizeof(groupcastaddr)) < 0)
        {
            err_log("fail to sendto");
        }

    }

    close(sockfd);
    return 0;
}

接收端(recv)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//组播接收的实现

#define N 128

#define err_log(errmsg) do{perror(errmsg); exit(1);}while(0)

int main(int argc, const char *argv[])
{
    int sockfd;
    struct sockaddr_in groupcastaddr;
    char buf[N] = {};

    if(argc < 3)
    {
        fprintf(stderr, "Usage: %s broadcast-ip-port.\n", argv[0]);
    }

    //第一步:创建套接字
    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        err_log("fail to socket");
    }

    //第二步:填充组播信息结构体
    groupcastaddr.sin_family = AF_INET;
    groupcastaddr.sin_addr.s_addr = inet_addr(argv[1]);
    groupcastaddr.sin_port = htons(atoi(argv[2]));

    //第三步:绑定套接字
    if(bind(sockfd, (struct sockaddr *)&groupcastaddr, sizeof(groupcastaddr)) < 0)
    {
        err_log("fail to bind");
    }

    socklen_t addrlen = sizeof(struct sockaddr_in);

    //第四步:将本机地址添加到组播组
    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(argv[1]); //组播地址
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);  //主机地址  INADDR_ANY 表示任意主机地址

    //允许加入多播组
    if(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
    {
        err_log("fail to setsockopt");
    }

    //第五步:接收消息
    while(1)
    {
        if(recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&groupcastaddr, &addrlen) < 0)
        {
            err_log("fail to recvfrom");
        }

        printf("groupcast >>> %s\n", buf);
    }

    close(sockfd);
    return 0;
}

你可能感兴趣的:(net)