UDP的广播与组播代码实现+解析

news/2024/5/18 14:41:51 标签: udp, 网络, 网络协议

UDP的广播与组播代码实现+解析

  • 一、UDP广播
    • 1.流程图
    • 2.直接广播与受限广播
    • 3.代码实现
      • 3.1代码说明
      • 3.2服务器代码
      • 3.3客户端
  • 二、UDP组播
    • 1.基础知识
    • 2.代码实现
      • 服务器
      • 客户端

一、UDP广播

1.流程图

在这里插入图片描述
说明:服务器发送数据报的时候源ip地址为广播地址,交换机解析到广播地址后发送到子网的所有主机的9000端口。

2.直接广播与受限广播

直接广播:直接广播地址包含一个有效的网络号和一个全“1”的主机号,如你说的202.163.30.255,255就是一个主机号,202则是C类的IP地址,C类IP地址就是我们常接触到的。 可用于本地网络,也可以跨网段广播。
受限广播:可以用在计算机不知道自己IP地址的时候,比如向DHCP服务器索要地址时、PPPOE拨号时等。路由器不允许它通过

3.代码实现

3.1代码说明

  1. 接收方一定要知道广播方的端口号,然后绑定此端口号才能正确接收。
  2. 接收方的Socket不需要设置成广播属性。
  3. 绑定的IP不可以使用“127.0.0.1”,可以使用真实IP地址或者INADDR_ANY。否则接收失败。

3.2服务器代码

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<sys/socket.h>
  5 #include<string.h>
  6 #include<arpa/inet.h>
  7 #include<net/if.h>
  8 
  9 #define CLIENT_PORT 9000
 10 #define MAXLINE  4096
 11 
 12 #define BROADCAST_IP  "192.168.99.255"
 13 
 14 int main(void)
 15 {
 16         int server_sockfd;
 17         struct sockaddr_in serveraddr , clientaddr;
 18         char buf[MAXLINE];
 19 
 20         //构造用于UDP通信的套接字
 21         server_sockfd = socket(AF_INET , SOCK_DGRAM , 0);
 22 
 23         int flag = 1;
 24         setsockopt(server_sockfd , SOL_SOCKET , SO_BROADCAST , &flag , sizeof(flag) );
 25 
 26         //构造client地址  IP+端口号 192.168.X.255+9000
 27         bzero(&clientaddr , sizeof(clientaddr));
 28         clientaddr.sin_family = AF_INET;
 29         inet_pton(AF_INET , BROADCAST_IP , &clientaddr.sin_addr.s_addr);
 30         clientaddr.sin_port = htons(CLIENT_PORT);
 31 
 32         int i=0;
 33         while(1){
 34                 sprintf(buf , "Drink %d glasses of water\n", i++);
 35                 sendto(server_sockfd , buf , strlen(buf) , 0 , (struct sockaddr *)&clientaddr , sizeof(clientaddr));
 36                 printf("%s",buf);
 37                 sleep(1);
 38 
 39         }
 40 
 41         close(server_sockfd);
 42         return 0;
 43 
 44 }

3.3客户端

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4 #include<sys/socket.h>
  5 #include<arpa/inet.h>
  6 
  7 #define SERVER_PORT 8000
  8 #define MAXLINE 4096
  9 #define CLIENT_PORT 9000
 10 
 11 int main(void)
 12 {
 13         struct sockaddr_in localaddr;
 14         int confd;
 15         ssize_t len;
 16         char buf[MAXLINE];
 17 
 18         //1.创建一个socket
 19         confd = socket(AF_INET , SOCK_DGRAM , 0);
 20 
 21         //2.初始化本地端地址--IP地址本地,端口号9000
 22         bzero(&localaddr , sizeof(localaddr));
 23         localaddr.sin_family = AF_INET;
 24         inet_pton(AF_INET , "0.0.0.0" , &localaddr.sin_addr.s_addr);
 25         localaddr.sin_port = htons(CLIENT_PORT);
 26 
 27         int ret = bind(confd , (struct sockaddr *)&localaddr , sizeof(locala    ddr));
 28         if(ret == 0)
 29                 printf("...bind ok...\n");
 30         while(1){
 31                 len = recvfrom(confd , buf , sizeof(buf),0,NULL,0);
 32                 printf("%s",buf);
 33 
 34         }
 35 
 36         close(confd);
 37         return 0;
 38 }

二、UDP组播

1.基础知识

  1. 组播报文的目的地址使用D类IP地址, D类地址不能出现在IP报文的源IP地址字段。
  2. 在ip组播环中,数据包的目的地址不是一个,而是一组,形成组地址。所有的信息接收者都加入到一个组内,并且一旦加入之后,流向组地址的数据立即开始向接收者传输,组中的所有成员都能接收到数据包。组播组中的成员是动态的,主机可以在任何时刻加入和离开组播组。
  3. 一个多播组的成员是随时变动的,一台主机可以随时加入或离开多播组,多播组成员的数目和所在的地理位置也不受限制,一台主机也可以属于几个多播组。此外,不属于某一个多播组的主机也可以向该多播组发送数据包。
  4. 多播作为一点对多点的通信,数据的收发仅仅在同一分组中进行,是节省网络带宽的有效方法之一

2.代码实现

服务器

1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <string.h>
  5 #include <arpa/inet.h>
  6 
  7 int main()
  8 {
  9     // 1. 创建通信的套接字
 10     int fd = socket(AF_INET, SOCK_DGRAM, 0);
 11     if(fd == -1)
 12     {
 13         perror("socket");
 14         exit(0);
 15     }
 16 
 17     // 设置组播属性
 18     struct in_addr imr_multiaddr;
 19     // 初始化组播地址
 20     inet_pton(AF_INET, "239.0.0.10", &imr_multiaddr.s_addr);
 21     setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &imr_multiaddr, sizeof(imr_m    ultiaddr));
 22 
 23     // 将数据发送给客户端, 使用广播地址和固定端口
 24     // 初始化客户端的地址信息
 25     struct sockaddr_in cliaddr;
 26     cliaddr.sin_family = AF_INET;
 27     cliaddr.sin_port = htons(8000); // 客户端也需要绑定这端口
 28     inet_pton(AF_INET, "239.0.0.10", &cliaddr.sin_addr.s_addr);
 29 
 30     int num = 0;
 31     // 3. 通信
 32     while(1)
 33     {
 34         // 接收数据
 35         char buf[128];
 36         // 发送数据
 37         sprintf(buf, "hello, client...%d\n ", num++);
 38         sendto(fd, buf, strlen(buf)+1, 0, (struct sockaddr*)&cliaddr, sizeof    (cliaddr));
 39         printf("组播的数据: %s\n", buf);
 40         sleep(1);
 41     }
 42     close(fd);
 43     return 0;
 44 }

客户端

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <string.h>
  5 #include <arpa/inet.h>
  6 #include <net/if.h>
  7 
  8 int main()
  9 {
 10     // 1. 创建通信的套接字
 11     int fd = socket(AF_INET, SOCK_DGRAM, 0);
 12     if(fd == -1)
 13     {
 14         perror("socket");
 15         exit(0);
 16     }
 17 
 18     // 2. 通信的fd绑定本地的IP和端口
 19     struct sockaddr_in addr;
 20     addr.sin_family = AF_INET;
 21     addr.sin_port = htons(8000);
 22     addr.sin_addr.s_addr = INADDR_ANY;
 23     int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
 24     if(ret == -1)
 25     {
 26         perror("bind");
 27         exit(0);
 28     }
 29     //inet_pton(AF_INET, "0.0.0.0", &addr.sin_addr.s_addr);
 30     // 加入到组播
 31     struct ip_mreqn op;
 32     op.imr_address.s_addr = INADDR_ANY; // 本地地址
 33     inet_pton(AF_INET, "239.0.0.10", &op.imr_multiaddr.s_addr);
 34     op.imr_ifindex = if_nametoindex("ens33");
 35 
 36     setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &op, sizeof(op));
 37     // 3. 通信
 38     while(1)
 39     {
 40         // 接收数据
 41         char buf[128];
 42         recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
 43         printf("server say: %s\n", buf);
 44     }
 45     close(fd);
 46     return 0;
 47 }

http://www.niftyadmin.cn/n/1371578.html

相关文章

vue3的一些改变

当你有一个子组件时 在里面添加click时候会默认他是emit发送的事件&#xff0c;你在那边接收&#xff0c;也就是一个自定义的事件&#xff0c;不会把他解析成一个onclick事件需要加.click.native才能被解析成原生事件 vue3中取消了native默认click就是原生事件&#xff0c;在…

HTTPS的安全性是如何保证的

HTTPS的安全性是如何保证的保证安全需要做到哪些点&#xff1f;1. 不能让第三方获取到明文消息1.1对称加密&#xff1a;指的就是加密和解密使用同一个秘钥1.2非对称加密&#xff1a;使用两个密钥&#xff1a;公钥和私钥&#xff0c;公钥可以任意分发而私钥保密1.2.1公钥和私钥的…

前端面试题 v-if和v-show的区别

简单来说&#xff0c;v-if 的初始化较快&#xff0c;但切换代价高&#xff1b;v-show 初始化慢&#xff0c;但切换成本低 v-if是动态的向DOM树内添加或者删除DOM元素&#xff1b; v-show是通过设置DOM元素的display样式属性控制显隐&#xff1b;

计算机网络面试高频考点

计算机网络面试高频考点 1.TCP三次握手过程 ①首先握手过程是建立在被动方处于监听状态。 ②客户端发送syn报文并随机一个序列号发送给服务器&#xff0c;此时客户端为syn_send状态&#xff0c; ③服务器收到syn报文后&#xff0c;发送给客户端一个synack报文&#xff0c;并随…

面试题 理解防抖及实现input的防抖

策略是当事件被触发时&#xff0c;设定一个周期延迟执行动作&#xff0c;若期间又被触发&#xff0c;则重新设定周期&#xff0c;直到周期结束&#xff0c;执行动作。 这是debounce的基本思想&#xff0c;在后期又扩展了前缘debounce&#xff0c;即执行动作在前&#xff0c;然后…

C++程序编译过程

C程序编译过程1.编译流程图2.预处理3.编译4.汇编5.链接1.编译流程图 2.预处理 编译器将C程序的头文件编译进来&#xff0c;还有宏的替换&#xff0c;可以用gcc的参数-E来参看。 主要处理源代码文件中的以“#”开头的预编译指令。处理规则见下 1、删除所有的#define&#xff…

C++多态、虚函数、虚函数表、编译期、运行期、静态、动态的理解

关于C多态1. 多态分为静态多态和动态多态1.1 静态多态1.1.1函数重载1.1.2模板1.1.3静态多态总结1.2 动态多态&#xff1a;在运行时期才能决定函数行为1.2.1先讲一些储备知识&#xff0c;不然初学者听着迷糊1.2.2 多态的体现&#xff1a;1.2.3 动态的体现1. 多态分为静态多态和动…

面试题 节流理解以及实现节流

类似王者荣耀的技能&#xff0c;冷却事件为5s在这5秒中咋点都不会放技能&#xff0c;当五秒过了才能放技能 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content…