• Linux 网络通信之组播


    组播可以看成是单播和广播的折中。当发送组播数据包时,只有加入指定多播组的主机数据链路层才会处理,其他主机在数据链路层会直接丢掉收到的数据包。即我们可以通过组播的方式和指定的若干台主机通信。

    D类地址:范围从224.0.0.1到239.255.255.254.此类地址又称为组播地址。每个组播地址代表一个多播组。

    组播包的发送和接收通过UDP套接字实现。

    组播包发送流程如下:

    (1)创建UDP套接字;socket(AF_INET, SOCK_DGRAM, 0)

    (2)指定目标地址和端口;struct sockaddr_in

    (3)发送数据包;sendto( )

    send.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <unistd.h>
     4 #include <sys/types.h>
     5 #include <sys/socket.h>
     6 #include <arpa/inet.h>
     7 #include <netinet/in.h>
     8 #include <string.h>
     9 
    10 #define  err_log(log) do{perror(log); exit(1);}while(0)
    11 
    12 #define  N 128
    13 
    14 int main(int argc, const char *argv[])
    15 {
    16     
    17     int sockfd;
    18     struct sockaddr_in groupcastaddr;
    19     char buf[N] = {0};
    20 
    21     if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    22     {
    23         err_log("fail to socket");
    24     }
    25 
    26     groupcastaddr.sin_family = AF_INET;
    27     groupcastaddr.sin_addr.s_addr = inet_addr("225.0.0.3");
    28     groupcastaddr.sin_port = htons(10000);
    29 
    30     while(1)
    31     {
    32         printf("Input > ");
    33         fgets(buf, N, stdin);
    34         if(sendto(sockfd,buf, N, 0, (struct sockaddr *)&groupcastaddr, sizeof(groupcastaddr)) < 0)
    35         {
    36             err_log("fail to sendto");
    37         }
    38         
    39     }
    40 
    41     return 0;
    42 }

    组播接收流程如下:

    (1)创建UDP套接字;socket(AF_INET, SOCK_DGRAM, 0)

    (2)加入多播组;setsockopt( )

    (3)填充组播地址信息(组播IP地址和端口);struct sockaddr_in

    (4)接收数据包;recvfrom( )

    多播结构体:

     1 struct ip_mreq                                                                                                    
     2 {
     3       /* IP multicast address of group.  */  组播的ip地址
     4       struct in_addr imr_multiaddr;
     5   
     6       /* Local IP address of interface.   */  本机的ip地址 
     7       struct in_addr imr_interface;
     8 };
     9 
    10 mreq.imr_multiaddr.s_addr = inet_addr(“224.10.10.1”);  //组播地址
    11 mreq.imr_interface.s_addr = htonl(INADDR_ANY);  //INADDR_ANY  0 地址 ,任意的主机地址
    12 
    13 setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

    recv.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <unistd.h>
     4 #include <sys/types.h>
     5 #include <sys/socket.h>
     6 #include <arpa/inet.h>
     7 #include <netinet/in.h>
     8 #include <string.h>
     9 
    10 #define  err_log(log) do{perror(log); exit(1);}while(0)
    11 #define  N  128
    12 
    13 int main(int argc, const char *argv[])
    14 {
    15     
    16     int sockfd;
    17     char buf[N];
    18     struct sockaddr_in groupcastaddr, srcaddr;
    19     struct ip_mreq mreq;
    20 
    21     if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    22     {
    23         err_log("fail to socket");
    24     }
    25     /*为套接字绑定组播地址和端口*/
    26     groupcastaddr.sin_family = AF_INET;
    27     groupcastaddr.sin_addr.s_addr = inet_addr("225.0.0.3");
    28     groupcastaddr.sin_port = htons(10000);
    29 
    30     /*加入多播组,允许数据链路层处理指定组播包*/
    31     mreq.imr_multiaddr.s_addr = inet_addr("225.0.0.3");
    32     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    33 
    34     if(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq, sizeof(mreq)) < 0)
    35     {
    36         err_log("fail to setsockopt");
    37     }
    38 
    39     int on = 1;
    40     if(setsockopt(sockfd,SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
    41     {
    42         err_log("fail to setsockopt");
    43     }
    44 
    45     if(bind(sockfd, (struct sockaddr*)&groupcastaddr, sizeof(groupcastaddr)) < 0)
    46     {
    47         err_log("fail to bind");
    48     }
    49 
    50     socklen_t addrlen = sizeof(struct sockaddr);
    51 
    52     while(1)
    53     {
    54         if(recvfrom(sockfd,buf, N, 0, (struct sockaddr *)&srcaddr, &addrlen) < 0)
    55         {
    56             err_log("fail to sendto");
    57         }
    58         printf("buf:%s ---> %s %d
    ", buf, inet_ntoa(srcaddr.sin_addr), ntohs(srcaddr.sin_port));
    59     }
    60 
    61     return 0;
    62 }
  • 相关阅读:
    js splice 属性实现数组的删除,插入,替换
    js var多等式变量的定义
    SQL Server 收缩数据库
    sql2005 全文索引
    显示器分辨率推荐
    使用javascript打开链接的多种方法
    运算优先级
    jqGrid
    asp.net IE 页面刷新固定位置
    Left Join ,On Where
  • 原文地址:https://www.cnblogs.com/yangziwen0709/p/5026028.html
Copyright © 2020-2023  润新知