如何在Linux环境下使用C语言实现UDP广播通信?

广播

在网络编程中,有三种常见的通信方式:单播、广播、多播(组播),以下是它们的对比:

如何在Linux环境下使用C语言实现UDP广播通信?插图1
(图片来源网络,侵删)
类型 IPv4 支持 IPv6 支持 TCP 支持 UDP 支持 所标识接口数 递送到的接口数
单播 支持 支持 支持 支持 一个 一个
广播 支持 不支持 不支持 支持 全体 全体
多播 可选 支持 不支持 支持 一组 整个组

广播是一种允许一台主机向本地子网内所有主机发送消息的通信方式,发送的广播分组会去往子网上的所有主机,包括发送者自身,广播只支持IPv4,不支持IPv6,并且仅支持UDP或原始IP,而不支持TCP。

广播地址

广播的实现需要往特定的广播地址发送广播分组,任何子网中最后一个IP地址就是广播地址,如果以{子网ID, 主机ID}表示一个IP地址,则广播地址分为以下两种:

1、子网定向广播地址:{子网ID, -1},这是子网上所有接口的广播地址,假设有一个192.168.1/24的子网,那么这个子网中的最后一个IP就是192.168.1.255/24,它就是该子网所有接口的子网定向广播地址,路由器不转发目的地址为子网定向广播地址的数据报。

2、受限广播地址:{-1, -1} 或 255.255.255.255,路由器从不转发目的地址为255.255.255.255的IP数据报,当应用程序设置了SO_BROADCAST套接字选项,且发送目的地址为255.255.255.255的UDP数据报时,大多数主机会将该目的地址转换成外出接口的子网定向广播地址并发送到路由器。

如何在Linux环境下使用C语言实现UDP广播通信?插图3
(图片来源网络,侵删)

UDP单播和UDP广播的比较

1、UDP单播过程

进程在一个UDP套接字上调用sendto往特定IP地址和端口发送一个数据报。

UDP层对数据报添加UDP首部后传递到IP层。

IP层添加IPv4首部,确定其外出接口,并在以太网情况下激活ARP把目的IP地址映射成相应的以太网地址。

如何在Linux环境下使用C语言实现UDP广播通信?插图5
(图片来源网络,侵删)

该分组作为一个以太网帧发送出去,只有目的主机接收并处理该帧。

2、UDP广播过程

进程在一个UDP套接字上调用sendto往IP地址192.168.42.255端口520发送一个数据报。

UDP层对数据报添加UDP首部后传递到IP层。

IP层添加IPv4首部,因为目的地址是子网定向广播地址,所以映射为48位全为1的以太网地址:ff:ff:ff:ff:ff:ff。

该分组作为一个以太网帧发送出去,使得该子网的每个以太网接口(包括自身主机接口)都会接收到该帧。

UDP广播的特点

面向无连接:UDP广播不需要建立连接,可以直接发送数据包到目标设备。

广播特性:UDP广播可以向一个网络中的所有设备发送数据包。

不可靠性:UDP广播发送的数据包无法保证传输的可靠性,可能会发生数据丢失、错误等情况。

速度快、开销小:由于UDP广播不需要建立连接,因此传输速度快,开销小,适用于实时流媒体传输等应用场景。

安全性较低:UDP广播发送的数据包可以被网络中的其他设备接收,可能会存在数据泄露的风险。

UDP广播的使用场景

视频和音频的实时传输:UDP广播可以使得多个设备同时接收到同一流的数据,实现实时的视频会议和音频播放等功能。

网络打印机的自动发现:通过UDP广播,打印机可以向网络中广播自己的存在,从而被所有的设备发现和使用。

多人游戏的联机:UDP广播可以将游戏数据同时发送给所有玩家的设备,实现多人游戏的联机功能。

网络摄像头的实时监控:通过UDP广播,摄像头可以将实时的视频流发送给所有监控软件,使得监控人员能够同时查看视频。

UDP广播编程示例

以下是一个简单的UDP广播发送和接收程序的示例:

服务端(广播端)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main() {
    int socket_desc;
    struct sockaddr_in server_addr;
    char *message;
    //创建原始套接字
    socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (socket_desc == -1) {
        printf("Could not create socket");
    }
    //设置广播权限
    int broadcast_permission = 1;
    int ret = setsockopt(socket_desc, SOL_SOCKET, SO_BROADCAST, &broadcast_permission, sizeof(broadcast_permission));
    if (ret == -1) {
        printf("Setsockopt failed");
    }
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8888);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    //绑定套接字到端口8888上
    bind(socket_desc, (struct sockaddr *)&server_addr, sizeof(server_addr));
    message = "Hello World!";
    sendto(socket_desc, message, strlen(message), 0, (struct sockaddr*)NULL, sizeof(struct sockaddr_in));
    return 0;
}

客户端(接收端)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main() {
    int socket_desc;
    struct sockaddr_in server_addr;
    char server_message[2000];
    //创建原始套接字
    socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (socket_desc == -1) {
        printf("Could not create socket");
    }
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8888);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    //绑定套接字到端口8888上
    bind(socket_desc, (struct sockaddr*)&server_addr, sizeof(server_addr));
    recvfrom(socket_desc, server_message, sizeof(server_message), 0, NULL, NULL);
    printf("Server : %s
", server_message);
    return 0;
}

以上就是关于“linux c udp广播”的问题,朋友们可以点击主页了解更多内容,希望可以够帮助大家!

本文来源于互联网,如若侵权,请联系管理员删除,本文链接:https://www.9969.net/71173.html

小末小末
上一篇 2024年10月8日 05:32
下一篇 2024年10月8日 05:42

相关推荐