当前位置: 首页 > news >正文

Linux下socket广播通讯的实现

概念大家都很清楚,不赘述。

广播必然用UDP这套东西。

setsockopt() 函数及其在广播中的应用:

在 C++ 网络编程中,setsockopt() 函数用于设置套接字选项,这些选项可以控制套接字的各种行为。对于广播通信,我们特别关心的是 SO_BROADCAST 选项,它允许套接字发送广播消息。

setsockopt() 函数原型

int setsockopt(int sockfd, int level, int option_name, const void *option_value, socklen_t option_len);
  • sockfd:要设置选项的套接字描述符。
  • level:指定选项所在的协议层。对于大多数套接字选项,这一层是 SOL_SOCKET,表示选项与套接字层本身相关。
  • option_name:要设置的选项的名称。对于广播选项,这是 SO_BROADCAST
  • option_value:指向一个变量的指针,该变量包含要设置的选项的值。对于 SO_BROADCAST,这个值通常是一个整数,非零表示启用广播,零表示禁用(尽管禁用广播通常不是必需的,因为默认情况下它可能是禁用的,除非特别启用)。
  • option_lenoption_value 指向的变量的长度,以字节为单位。对于 SO_BROADCAST,这通常是 sizeof(int)

SO_BROADCAST 选项

  • 作用:允许套接字发送广播消息。广播消息是发送到网络上的所有主机的消息,这些主机都监听特定的广播地址和端口。
  • 默认值:在大多数系统上,套接字默认不允许发送广播消息,必须显式启用。
  • 使用场景:当您希望向网络上的多个主机发送相同的信息时,广播非常有用。例如,在局域网中查找服务或设备时。

框架示例代码

以下是如何在 C++ 中使用 setsockopt() 启用 SO_BROADCAST 选项的示例代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>int main() {int sockfd;int broadcastEnable = 1; // 启用广播// 创建 UDP 套接字sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("socket creation failed");return 1;}// 启用广播选项if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)) < 0) {perror("setsockopt(SO_BROADCAST) failed");close(sockfd);return 1;}// ... 在这里发送广播消息 ...// 关闭套接字close(sockfd);return 0;
}

在这个例子中,我们首先创建了一个 UDP 套接字,然后使用 setsockopt() 函数启用了 SO_BROADCAST 选项。之后,我们可以使用 sendto() 函数发送广播消息。最后,我们关闭了套接字。

完整的广播的过程:

在 linux 中使用套接字(socket)进行广播通信,通常涉及以下几个步骤:

  1. 创建套接字:使用 socket() 函数创建一个 UDP 套接字,因为 UDP 支持广播。
  2. 设置广播选项:使用 setsockopt() 函数启用广播选项。
  3. 绑定套接字(可选):如果你希望绑定到特定的端口和/或 IP 地址,可以使用 bind() 函数。
  4. 发送广播消息:使用 sendto() 函数将消息发送到广播地址(通常是 255.255.255.255)。

下面是一个简单的示例代码,展示了如何在 linux 中使用套接字进行广播通信:

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h> // 注意:在某些系统上可能是 <netinet/in.h>,但 <arpa/inet.h> 通常包含了它
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h> // 包含 exit 和 EXIT_FAILURE 的定义#define PORT 8080
#define BROADCAST_IP "255.255.255.255"
#define BUFFER_SIZE 1024int main() {int sockfd;struct sockaddr_in broadcastAddr;const char *message = "Hello, this is a broadcast message!";char buffer[BUFFER_SIZE];// 创建 UDP 套接字if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}int broadcastEnable = 1;// 启用广播选项if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)) < 0) {perror("setsockopt(SO_BROADCAST) failed");close(sockfd);exit(EXIT_FAILURE);}// 设置广播地址和端口memset(&broadcastAddr, 0, sizeof(broadcastAddr));broadcastAddr.sin_family = AF_INET;broadcastAddr.sin_addr.s_addr = inet_addr(BROADCAST_IP);broadcastAddr.sin_port = htons(PORT);// 发送广播消息if (sendto(sockfd, message, strlen(message), MSG_CONFIRM, (const struct sockaddr*)&broadcastAddr, sizeof(broadcastAddr)) < 0) {perror("sendto failed");close(sockfd);exit(EXIT_FAILURE);}printf("Broadcast message sent: %s\n", message);// 关闭套接字close(sockfd);return 0;
}

 注意事项

  1. 权限:在某些操作系统(如 Linux)上,发送广播消息可能需要管理员权限。如果遇到权限问题,可以尝试以 root 用户运行程序,或者使用 sudo 命令。
  2. 防火墙:确保防火墙设置允许广播消息的发送和接收。
  3. 网络配置:确保网络配置允许广播通信。

接收广播消息

要接收广播消息,你需要创建一个监听特定端口和地址(通常是 INADDR_ANY)的套接字,然后等待接收数据。以下是一个简单的接收广播消息的示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h> // 注意:在某些系统上可能是<netinet/in.h>的一部分或别名
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>#define PORT 8080
#define BUFFER_SIZE 1024int main() {int sockfd;struct sockaddr_in serverAddr, clientAddr;socklen_t addrLen = sizeof(clientAddr);char buffer[BUFFER_SIZE];// 创建 UDP 套接字if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}// 绑定套接字到指定端口memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = INADDR_ANY;serverAddr.sin_port = htons(PORT);if (bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {perror("bind failed");close(sockfd);exit(EXIT_FAILURE);}// 接收广播消息(注意:这里应该是阻塞等待,直到收到消息)ssize_t numBytes = recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0, (struct sockaddr*)&clientAddr, &addrLen);if (numBytes < 0) {perror("recvfrom failed");close(sockfd);exit(EXIT_FAILURE);}// 确保字符串以null字符结尾buffer[numBytes] = '\0';// 使用printf输出接收到的消息printf("Received broadcast message: %s\n", buffer);// 关闭套接字close(sockfd);return 0;
}

这个接收程序将监听指定的端口,并打印接收到的广播消息。确保接收程序和发送程序在相同的网络环境中运行,并且端口号匹配。

这里服务器套接字被绑定到了指定的端口(PORT,即8080),并且它准备好接收来自任何IP地址的数据报(因为serverAddr.sin_addr.s_addr被设置为INADDR_ANY)。由于套接字是UDP类型的,并且没有设置特定的广播接收选项(实际上,对于UDP套接字来说,接收广播消息是默认启用的),因此该套接字能够接收发送到该端口上的任何UDP数据报,包括广播消息。

然而,代码本身并没有特别指定它只接收来自某个特定广播地址的消息。当recvfrom()函数被调用时,它会阻塞(除非套接字被设置为非阻塞模式),直到有数据报到达绑定的端口。一旦数据报到达,recvfrom()会填充clientAddr结构体以反映发送方的IP地址和端口号。

要知道广播消息的实际来源广播地址,您可以检查clientAddr.sin_addr字段。这个字段包含了发送方的IP地址,如果这是一个广播消息,那么它应该是您网络上的广播地址(比如255.255.255.255对于本地广播,或者是子网特定的广播地址,比如192.168.1.255对于子网192.168.1.0/24)。但是,请注意,如果发送方不在同一个子网内,并且是通过路由器发送的广播消息(这通常是不被允许的,因为广播消息通常不会跨子网路由),那么clientAddr可能会显示发送方的实际IP地址,而不是广播地址。

在实际应用中,如果您想要接收特定广播地址上的消息,您通常需要在网络上有一个已知的广播地址,并且您的应用程序需要知道这个地址。然而,由于UDP广播的本地性质,您的应用程序通常只能接收到来自同一子网内的广播消息,除非有特殊的路由配置允许跨子网的广播。

另外,值得注意的是,在现代网络环境中,由于安全和维护方面的原因,许多网络都配置为不允许或限制广播消息的传播。因此,在实际部署基于UDP广播的应用程序时,您可能需要考虑这些因素。


http://www.mrgr.cn/news/80125.html

相关文章:

  • Java-DataX 插件机制示例
  • 计算机网络中的三大交换技术详解与实现
  • 服务器---centos上安装docker并使用docker配置jenkins
  • 智能家居与AI物联网的无缝连接:构建个性化、智能化的居住体验
  • 打造微信小程序中的视频播放交互体验:videoUI组件库实战
  • Tomcat项目本地部署
  • 图像融合算法笔记2024 CDTNet
  • pytorch_fid 安装笔记
  • 【AIGC】ChatGPT保护指令:高效提升GPTs提示词与知识库文件的安全性
  • 【PyCharm调试】显示一个对象值时会调用的方法
  • 长短期记忆神经网络(LSTM)介绍
  • 【ADS射频电路学习笔记】1. ADS基本操作
  • PHP搭建环境
  • depth wisepoint wise
  • 【收藏】Cesium 限制相机倾斜角(pitch)滑动范围
  • faster-RCNN训练【环境配置→自建数据集→训练→改错】
  • C语言实现八大排序算法
  • 【C语言】库函数常见的陷阱与缺陷(六):输入输出函数
  • kubeadm安装K8s集群之高可用组件keepalived+nginx及kubeadm部署
  • OSPF协议
  • ubuntu20.04复现 Leg-KILO
  • centos7的yum镜像源设置
  • 暂停一下,给Next.js项目配置一下ESLint(Next+tailwind项目)
  • 程序的调试
  • 6.2 MapReduce工作原理
  • QT笔记- QSystemTrayIcon系统托盘功能完整示例