计算机网络 | 广播与组播

简介: 计算机网络 | 广播与组播

首先需要明确的是,广播和组播都是UDP的属性,在TCP中是没有的。

1. 广播

广播的例子随处可见,比如说把屏幕共享给很多人,其实也是广播,首先把屏幕截图,然后广播给所有的客户端,比如说屏幕共享软件,一般都有一个广播地址,只要在同一个网段的客户端都能收到广播,如果设置广播地址为255.255.255.255,那么不管哪个网段都能收到广播。屏幕共享软件会把当前屏幕截图并分为很多小块,然后压缩,广播给所有客户端,客户端再进行解压。

广播的工作过程:

  • 服务器
  • 创建套接字 —— socket
  • fd绑定服务器IP和端口
  • 初始化客户端IP和端口信息
  • struct sockaddr_in cli;
  • cli.sin_family = af_inet;
  • cli.port = htons(9898);
  • inet_pton(af_inet, “xxx.xxx.123.255”, &cli.adr);
  • 发送数据:sendto()
  • 设置广播权限(给服务器,server虽然设置了广播地址,但是默认是没有广播权限的)
  • setsockopt();
  • 客户端
  • 创建套接字
  • 显式绑定IP和端口
  • bind();
  • 接收数据 —— server数据
  • recvform();
  • 适用范围
  • 只适用于局域网

server只发数据(主动),client只收数据(被动)。不管client想不想接收,server都会发,只要client在server的发送范围内(局域网),就必须收。UDP发送数据需要client的IP和port,而每个client都有自己的不同的IP,所以server需要一个广播地址,只要把数据发送到这个广播地址,所有在同一网段的client都可以收到,同时需要绑定一个固定端口。如果是同一台主机测试广播的话,server和client应该用不同的端口(一个端口只能给一个进程用),如果server和client是不同的主机,那就无所谓了。

2. 组播

组播也叫做多播,组播组可以是永久的也可以是临时的。组播组地址中,有一部分由官方分配的,称为永久组播组。永久组播组保持不变的是它的ip地址,组中的成员构成可以发生变化。永久组播组中成员的数量都可以是任意的,甚至可以为零。那些没有保留下来供永久组播组使用的ip组播地址,可以被临时组播组利用。

  • 组播的适用范围
  • 局域网
  • Internet —— 广域网
  • 组播地址
  • 224.0.0.0~224.0.0.255 —— 预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用。
  • 224.0.1.0~224.0.1.255 —— 公用组播地址,可以用于Internet,想要使用需申请。
  • 224.0.2.0~238.255.255.255 —— 用户可用的组播地址(临时组地址),全网范围内有效。
  • 239.0.0.0~239.255.255.255 —— 本地管理组播地址,仅在特定的本地范围内有效。
  • 两个结构体
struct ip_mreqn
{
  // 组播组的IP地址,即组播地址。
    struct  in_addr imr_multiaddr; 
    // 本地某一网络设备接口的IP地址。
    struct  in_addr imr_interface; //设置 0.0.0.0 自动适配本机IP   
  int     imr_ifindex; // 网卡编号
};
struct in_addr 
{
  in_addr_t s_addr;
};

使用函数可以通过网卡名字获取网卡编号

unsigned if_nametoindex(const char *ifname); //根据网卡名字获取网卡编号

组播示意图如下:

server指定一个组播地址,并向组播地址发送数据,client要想接收数据就要加入这个组播地址。

server

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <net/if.h>
#define SERVER_PORT 6666
#define CLIENT_PORT 9000
#define MAXLINE 1500
#define GROUP "239.0.0.2"
int main(void)
{
  int sockfd, i ;
  struct sockaddr_in serveraddr, clientaddr;
  char buf[MAXLINE] = "itcast\n";
  char ipstr[INET_ADDRSTRLEN]; /* 16 Bytes */
  socklen_t clientlen;
  ssize_t len;
  struct ip_mreqn group;
  /* 构造用于UDP通信的套接字 */
  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  bzero(&serveraddr, sizeof(serveraddr));
  serveraddr.sin_family = AF_INET; /* IPv4 */
  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); /* 本地任意IP INADDR_ANY = 0 */
  serveraddr.sin_port = htons(SERVER_PORT);
  bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
  /*设置组地址*/
  inet_pton(AF_INET, GROUP, &group.imr_multiaddr);
  /*本地任意IP*/
  inet_pton(AF_INET, "0.0.0.0", &group.imr_address);
  /* eth0 --> 编号 命令:ip ad */
  group.imr_ifindex = if_nametoindex("eth0");
  setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &group, sizeof(group));
  /*构造 client 地址 IP+端口 */
  bzero(&clientaddr, sizeof(clientaddr));
  clientaddr.sin_family = AF_INET; /* IPv4 */
  inet_pton(AF_INET, GROUP, &clientaddr.sin_addr.s_addr);
  clientaddr.sin_port = htons(CLIENT_PORT);
  while (1) {
    //fgets(buf, sizeof(buf), stdin);
    sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&clientaddr, sizeof(clientaddr));
    sleep(1);
  }
  close(sockfd);
  return 0;
}

client

#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <net/if.h>
#define SERVER_PORT 6666
#define MAXLINE 4096
#define CLIENT_PORT 9000
#define GROUP "239.0.0.2"
int main(int argc, char *argv[])
{
  struct sockaddr_in serveraddr, localaddr;
  int confd;
  ssize_t len;
  char buf[MAXLINE];
  /* 定义组播结构体 */
  struct ip_mreqn group;
  confd = socket(AF_INET, SOCK_DGRAM, 0);
  //初始化本地端地址
  bzero(&localaddr, sizeof(localaddr));
  localaddr.sin_family = AF_INET;
  inet_pton(AF_INET, "0.0.0.0" , &localaddr.sin_addr.s_addr);
  localaddr.sin_port = htons(CLIENT_PORT);
  bind(confd, (struct sockaddr *)&localaddr, sizeof(localaddr));
  /*设置组地址*/
  inet_pton(AF_INET, GROUP, &group.imr_multiaddr);
  /*本地任意IP*/
  inet_pton(AF_INET, "0.0.0.0", &group.imr_address);
  /* eth0 --> 编号 命令:ip ad */
  group.imr_ifindex = if_nametoindex("eth0");
  /*设置client 加入多播组 */
  setsockopt(confd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group));
  while (1) {
    len = recvfrom(confd, buf, sizeof(buf), 0, NULL, 0);
    write(STDOUT_FILENO, buf, len);
  }
  close(confd);
  return 0;
}

相关文章
|
2月前
|
网络协议 Unix C语言
C语言 网络编程(十六)广播和组播
广播和组播是网络通信的重要方式。广播允许一台主机向子网内所有主机发送数据包,常用于局域网内的消息传播;组播则将数据包发送给特定的一组主机,适用于视频会议等应用场景。广播地址如 `192.168.1.255` 用于同一子网的所有主机。组播地址如 `224.0.0.0` 至 `239.255.255.255` 标识特定主机群。C语言示例展示了如何通过 UDP 实现广播和组播通信。此外,UNIX域套接字用于同一机器上进程间的高效通信。
135 14
|
6月前
|
监控 网络架构 负载均衡
|
6月前
|
前端开发 网络安全 网络架构
【华为数通HCIP | 网络工程师】821-BGP 组播高频题与解析(1)
【华为数通HCIP | 网络工程师】821-BGP 组播高频题与解析(1)
428 0
|
6月前
|
网络协议 算法 网络架构
计算机网络:网络层(IP组播)
计算机网络:网络层(IP组播)
|
6月前
|
缓存 算法 网络架构
【网络层】IP组播(多播)、硬件组播、IGMP、组播路由选择协议、移动IP、路由器详解、路由表和路由转发
【网络层】IP组播(多播)、硬件组播、IGMP、组播路由选择协议、移动IP、路由器详解、路由表和路由转发
149 0
|
Cloud Native 块存储
阿里云最新产品手册——阿里云核心产品——块存储——飞天洛神3.0——云网络发展历程——云网络3.0时代——云原生组播能力
阿里云最新产品手册——阿里云核心产品——块存储——飞天洛神3.0——云网络发展历程——云网络3.0时代——云原生组播能力自制脑图
210 1
|
网络协议
Qt网络编程之搭建Udp通信【单播、组播、广播】
Qt网络编程之搭建Udp通信【单播、组播、广播】
833 0
|
网络协议 算法 网络架构
【计算机网络】网络层 : IP 组播 ( IP 数据报传输方式 | 组播 IP 地址 | 组播 MAC 地址 | IGMP 协议 | 组播路由选择协议 )
【计算机网络】网络层 : IP 组播 ( IP 数据报传输方式 | 组播 IP 地址 | 组播 MAC 地址 | IGMP 协议 | 组播路由选择协议 )
389 0
【计算机网络】网络层 : IP 组播 ( IP 数据报传输方式 | 组播 IP 地址 | 组播 MAC 地址 | IGMP 协议 | 组播路由选择协议 )