• l8-d19 广播与组播


    一、广播

    1.概念

    数据包发送方式只有一个接受方,称为单播

    如果同时发给局域网中的所有主机,称为广播

    只有用户数据报(使用UDP协议)套接字才能广播

    广播地址

    一个网络内主机号全为1的IP地址为广播地址

    发到该地址的数据包被所有的主机接收

    255.255.255.255在所有网段中都代表广播地址

    int on = 1;

    setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

    2.实现

     发送端

    1. #include
    2. #include
    3. #include
    4. #include /* superset of previous */
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #define ErrExit(msg) do {perror(msg); exit(EXIT_FAILURE);} while(0)
    11. typedef struct sockaddr Addr;
    12. typedef struct sockaddr_in Addr_in;
    13. int main(int argc, char *argv[])
    14. {
    15. int fd = -1;
    16. Addr_in peeraddr;
    17. socklen_t peerlen = sizeof(peeraddr);
    18. char buf[BUFSIZ] = {};
    19. /*参数检查*/
    20. if(argc < 3){
    21. fprintf(stderr, "%s", argv[0]);
    22. exit(EXIT_FAILURE);
    23. }
    24. /*创建套接字*/
    25. if( (fd = socket(AF_INET, SOCK_DGRAM, 0) ) < 0)
    26. ErrExit("socket");
    27. /*允许广播*/
    28. int on = 1;
    29. setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
    30. /*设置通信结构体*/
    31. peeraddr.sin_family = AF_INET;
    32. peeraddr.sin_port = htons(atoi(argv[2]));
    33. if(!inet_aton(argv[1], &peeraddr.sin_addr) ){
    34. fprintf(stderr, "Invalid address\n");
    35. exit(EXIT_FAILURE);
    36. }
    37. while(1){
    38. fgets(buf, BUFSIZ, stdin);
    39. sendto(fd, buf, strlen(buf)+1, 0, (Addr *)&peeraddr, peerlen);
    40. }
    41. return 0;
    42. }

    接收端

    1. #include
    2. #include
    3. #include
    4. #include /* superset of previous */
    5. #include
    6. #include
    7. #include
    8. #include
    9. #define ErrExit(msg) do {perror(msg); exit(EXIT_FAILURE);} while(0)
    10. typedef struct sockaddr Addr;
    11. typedef struct sockaddr_in Addr_in;
    12. int main(int argc, char *argv[])
    13. {
    14. int fd = -1;
    15. Addr_in myaddr, peeraddr;
    16. socklen_t peerlen = sizeof(peeraddr);
    17. char buf[BUFSIZ] = {};
    18. /*参数检查*/
    19. if(argc < 3){
    20. fprintf(stderr, "%s", argv[0]);
    21. exit(EXIT_FAILURE);
    22. }
    23. /*创建套接字*/
    24. if( (fd = socket(AF_INET, SOCK_DGRAM, 0) ) < 0)
    25. ErrExit("socket");
    26. /*设置通信结构体*/
    27. myaddr.sin_family = AF_INET;
    28. myaddr.sin_port = htons(atoi(argv[2]));
    29. if(!inet_aton(argv[1], &myaddr.sin_addr) ){
    30. fprintf(stderr, "Invalid address\n");
    31. exit(EXIT_FAILURE);
    32. }
    33. /*绑定通信结构体*/
    34. if( bind(fd, (Addr *)&myaddr, sizeof(Addr_in)) )
    35. ErrExit("bind");
    36. while(1){
    37. recvfrom(fd, buf, BUFSIZ, 0, (Addr *)&peeraddr, &peerlen);
    38. printf("[%s:%d]%s\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port), buf);
    39. }
    40. return 0;
    41. }

    二、组播

    1.概念

    多播 IP 地址

            在 IP 多播数据报的目的地址需要写入多播组的标识符。

            多播组的标识符就是 IP 地址中的 D 类地址(多播地址)。

            地址范围:224.0.0.0 ~ 239.255.255.255

            每一个 D 类地址标志一个多播组。

            多播地址只能用于目的地址,不能用于源地址。

    组播的实现

            创建用户数据报套接字

            加入多播组

            绑定组播IP地址和端口

            等待接收数据

    多个网卡

    struct ip_mreqn {

        struct in_addr imr_multiaddr;  /*IP 组播组地址*/

        struct in_addr imr_address;   /*本地接口的IP地址*/

        int                   imr_ifindex;   /*本地网卡的编号*/

    }

    if(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0){

    perror("setsockopt");

    exit(0);

    }

    单一网卡

    struct ip_mreq {

        struct in_addr imr_multiaddr;  /*IP 组播组地址*/

        struct in_addr imr_address;   /*本地接口的IP地址*/

    }

    if(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0){

    perror("setsockopt");

    exit(0);

    }

    2.实现

    接收端

    1. #include
    2. #include
    3. #include
    4. #include /* superset of previous */
    5. #include
    6. #include
    7. #include
    8. #include
    9. #define ErrExit(msg) do {perror(msg); exit(EXIT_FAILURE);} while(0)
    10. typedef struct sockaddr Addr;
    11. typedef struct sockaddr_in Addr_in;
    12. int main(int argc, char *argv[])
    13. {
    14. int fd = -1;
    15. Addr_in myaddr, peeraddr;
    16. socklen_t peerlen = sizeof(peeraddr);
    17. struct ip_mreqn mreq;
    18. char buf[BUFSIZ] = {};
    19. /*参数检查*/
    20. if(argc < 3){
    21. fprintf(stderr, "%s", argv[0]);
    22. exit(EXIT_FAILURE);
    23. }
    24. /*创建套接字*/
    25. if( (fd = socket(AF_INET, SOCK_DGRAM, 0) ) < 0)
    26. ErrExit("socket");
    27. /*加入多播组*/
    28. bzero(&mreq, sizeof(mreq) );
    29. if(!inet_aton(argv[1], &mreq.imr_multiaddr) ){
    30. fprintf(stderr, "Invalid address\n");
    31. exit(EXIT_FAILURE);
    32. }
    33. if(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0){
    34. perror("setsockopt");
    35. exit(0);
    36. }
    37. /*设置通信结构体*/
    38. myaddr.sin_family = AF_INET;
    39. myaddr.sin_port = htons(atoi(argv[2]));
    40. if(!inet_aton(argv[1], &myaddr.sin_addr) ){
    41. fprintf(stderr, "Invalid address\n");
    42. exit(EXIT_FAILURE);
    43. }
    44. /*绑定通信结构体*/
    45. if( bind(fd, (Addr *)&myaddr, sizeof(Addr_in)) )
    46. ErrExit("bind");
    47. while(1){
    48. recvfrom(fd, buf, BUFSIZ, 0, (Addr *)&peeraddr, &peerlen);
    49. printf("[%s:%d]%s\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port), buf);
    50. }
    51. return 0;
    52. }

    发送端

    1. #include
    2. #include
    3. #include
    4. #include /* superset of previous */
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #define ErrExit(msg) do {perror(msg); exit(EXIT_FAILURE);} while(0)
    11. typedef struct sockaddr Addr;
    12. typedef struct sockaddr_in Addr_in;
    13. int main(int argc, char *argv[])
    14. {
    15. int fd = -1;
    16. Addr_in peeraddr;
    17. socklen_t peerlen = sizeof(peeraddr);
    18. char buf[BUFSIZ] = {};
    19. /*参数检查*/
    20. if(argc < 3){
    21. fprintf(stderr, "%s", argv[0]);
    22. exit(EXIT_FAILURE);
    23. }
    24. /*创建套接字*/
    25. if( (fd = socket(AF_INET, SOCK_DGRAM, 0) ) < 0)
    26. ErrExit("socket");
    27. /*设置通信结构体*/
    28. peeraddr.sin_family = AF_INET;
    29. peeraddr.sin_port = htons(atoi(argv[2]));
    30. if(!inet_aton(argv[1], &peeraddr.sin_addr) ){
    31. fprintf(stderr, "Invalid address\n");
    32. exit(EXIT_FAILURE);
    33. }
    34. while(1){
    35. fgets(buf, BUFSIZ, stdin);
    36. sendto(fd, buf, strlen(buf)+1, 0, (Addr *)&peeraddr, peerlen);
    37. }
    38. return 0;
    39. }

    Makefile

    CC=gcc
    CFLAGS=-g -Wall
    all:receiver sender

    clean:
        -rm receiver sender
     

  • 相关阅读:
    Scala (十二) --------- IDEA 快捷键
    C++多线程学习
    关于指针初始化为NULL的一些问题
    5‘-荧光素氨基磷酸酯,CAS号: 204697-37-0
    常见亲脂性细胞膜染料DiO, Dil, DiR, Did光谱图和实验操作流程
    Oracle数据库从入门到精通系列之十二:段
    服务器出现了一个新软件,一帮大佬吵起来了!
    【Python】Python 包 ③ ( Python 第三方包简介 | 安装第三方包 | 命令行安装 | PyCharm 安装 | 设置代理 | 使用第三方包开发 )
    【雷达通信】Matlab实现广义自适应多项式窗函数
    Java手写最大流算法应用拓展案例
  • 原文地址:https://blog.csdn.net/revengeman/article/details/132949644