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

一、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 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长不大的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值