C语言组播的使用

C语言网络编程实现广播、组播及本地通信 本文介绍了广播、组播和本地通信,及其网络编程实现,并给出一个小项目作为网络编程专栏的总体练习 阅读详情

目录

一、组播的初始化和关闭

        1、multicast_util.h

        2、multicast_util.c

        使用示例:

        3、绑定本地地址时的区别

二、相关函数和介绍

         1、setsockopt函数介绍

                a、setsockopt函数原型

                 b、setsockopt函数参数介绍

 SOL_SOCKET 层(通用套接字选项)

 IPPROTO_IP 层(IPv4 选项)

IPPROTO_TCP 层(TCP 选项)

        2、inet_ntop 函数和 inet_pton函数详解 

                a、函数原型

        参数说明:

        返回值:

                b、使用示例


一、组播的初始化和关闭

        1、multicast_util.h

#ifndef MULTICAST_UTIL_H
#define MULTICAST_UTIL_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief 初始化 UDP 组播套接字
 * @param group_ip   组播地址字符串,如 "227.0.80.44"
 * @param port       本地绑定端口
 * @param iface      网络接口名,如 "eth0"。若为 NULL 则使用 INADDR_ANY
 * @param timeout_sec 接收超时秒数,0 表示不设置超时
 * @param buffer_size 接收缓冲区大小(字节),0 表示使用系统默认值
 * @return 成功返回套接字描述符,失败返回 -1
 */
int multicast_init(const char *group_ip, uint16_t port,
                   const char *iface, int timeout_sec,
                   int buffer_size);

/**
 * @brief 关闭组播套接字并离开组播组(可选,直接 close 也可)
 * @param sock 套接字描述符
 * @param group_ip 组播地址(用于离开组播组,可传入 NULL,但最好提供)
 */
void multicast_close(int sock, const char *group_ip);

#ifdef __cplusplus
}
#endif

#endif // MULTICAST_UTIL_H

        2、multicast_util.c

#include "multicast_util.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <sys/ioctl.h>

/**
 * @brief 根据网络接口名获取 IPv4 地址
 * @param ifname 接口名,如 "eth0"
 * @param ip_buf 输出缓冲区,至少 INET_ADDRSTRLEN 大小
 * @return 0 成功,-1 失败
 */
static int get_iface_ip(const char *ifname, char *ip_buf)
{
    int fd;
    struct ifreq ifr;
    struct sockaddr_in *sin;

    if (!ifname || !ip_buf)
        return -1;

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0)
        return -1;

    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
    ifr.ifr_name[IFNAMSIZ - 1] = '\0';

    if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
        close(fd);
        return -1;
    }

    sin = (struct sockaddr_in *)&ifr.ifr_addr;
    inet_ntop(AF_INET, &sin->sin_addr, ip_buf, INET_ADDRSTRLEN);
    close(fd);
    return 0;
}

int multicast_init(const char *group_ip, uint16_t port,
                   const char *iface, int timeout_sec,
                   int buffer_size)
{
    int sock;
    struct sockaddr_in local_addr;  //本地ip信息
    struct ip_mreq mreq;            //组播信息
    int reuse = 1;
    struct timeval tv;
    int ret;

    if (!group_ip)
        return -1;

    // 初始化 UDP 套接字
    sock = socket(AF_INET, SOCK_DGRAM, 0);  
    if (sock < 0) {
        perror("socket");
        return -1;
    }

    // 允许地址重用
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
        perror("setsockopt SO_REUSEADDR");
        close(sock);
        return -1;
    }

    // 绑定本地端口
    memset(&local_addr, 0, sizeof(local_addr));
    local_addr.sin_family = AF_INET;  //指定地址族为 IPv4。
    /*套接字将绑定到本机所有可用的网络接口 一般建议绑定到INADDR_ANY,然后通过IP_ADD_MEMBERSHIP指定接口,这样任何到达该端口的组播数据(无论哪个接口)都会被接收*/
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    local_addr.sin_port = htons(port);

    if (bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
        perror("bind");
        close(sock);
        return -1;
    }

    // 准备加入组播组
    memset(&mreq, 0, sizeof(mreq));
    mreq.imr_multiaddr.s_addr = inet_addr(group_ip);

    if (iface && iface[0] != '\0') {
        // 获取指定接口的 IP 地址
        char ip_str[INET_ADDRSTRLEN];
        if (get_iface_ip(iface, ip_str) == 0) {
            inet_pton(AF_INET, ip_str, &mreq.imr_interface.s_addr);
        } else {
            // 获取失败,回退到 INADDR_ANY
            mreq.imr_interface.s_addr = htonl(INADDR_ANY);
            fprintf(stderr, "Warning: failed to get IP of interface %s, using INADDR_ANY\n", iface);
        }
    } else {
        // 未指定接口,使用默认
        mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    }

    // 加入组播组
    if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        perror("setsockopt IP_ADD_MEMBERSHIP");
        // 尝试用 INADDR_ANY 重试一次
        mreq.imr_interface.s_addr = htonl(INADDR_ANY);
        if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
            perror("setsockopt IP_ADD_MEMBERSHIP (second attempt)");
            close(sock);
            return -1;
        }
    }

    // 设置接收超时(如果需要)
    if (timeout_sec > 0) {
        tv.tv_sec = timeout_sec;
        tv.tv_usec = 0;
        if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
            perror("setsockopt SO_RCVTIMEO");
            // 超时非必须,继续
        }
    }

    // 设置接收缓冲区大小(如果需要)
    if (buffer_size > 0) {
        if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &buffer_size, sizeof(buffer_size)) < 0) {
            perror("setsockopt SO_RCVBUF");
            // 缓冲区非必须,继续
        }
    }

    return sock;
}

void multicast_close(int sock, const char *group_ip)
{
    if (sock < 0)
        return;

    if (group_ip) {
        struct ip_mreq mreq;
        memset(&mreq, 0, sizeof(mreq));
        mreq.imr_multiaddr.s_addr = inet_addr(group_ip);
        mreq.imr_interface.s_addr = htonl(INADDR_ANY);
        // 忽略错误,因为套接字即将关闭
        (void)setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
    }

    close(sock);
}

        使用示例:

#include "multicast_util.h"
#include <stdio.h>
#include <unistd.h>

int main()
{
    //组播初始化 指定端口38888,指定加入的网卡为:eth0, 接收5s超时,缓存区大小设置 4M
    int sock = multicast_init("227.0.85.33", 38888, "eth0", 5, 4*1024*1024);
    if (sock < 0) {
        fprintf(stderr, "Failed to init multicast\n");
        return 1;
    }

    char buf[4096];
    struct sockaddr_in src;
    socklen_t srclen = sizeof(src);
    while(1)
    { 
        ssize_t n = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&src, &srclen);
        if (n > 0) {
            printf("Received %zd bytes from %s:%d\n", n, inet_ntoa(src.sin_addr), ntohs(src.sin_port));
            //这里进行具体的数据操作或者传入队列等》》》》》》

    
        }
    }

    multicast_close(sock, "227.0.81.22");
    return 0;
}

        以上组播初始化中,INADDR_ANY 表示套接字绑定到所有可用的本地网络接口(即监听或接收来自任何网络接口的数据,对于UDP,这意味着它可以接收发送到该端口的数据包,无论数据包到达哪个本地IP地址(即任意源IP都可以发送数据到这个端口,但目的IP必须是本机的某个IP)。因此,它并不是“允许任意IP连接”,而是“允许通过任意本地网络接口接收数据”。

        之后,程序会查找本地网卡"eth0"的网卡信息,如果eth0网卡存在符合的ip配置信息,则程序会将该ip信息加入组播,如果获取失败则使用任意ip信息。

        如果你想固定直接绑定本地IP地址可以进行如下修改:

// 创建 UDP 套接字
.....

// 允许地址重用
.....

//先获取本地IP信息
char eth0_ip[INET_ADDRSTRLEN];
if (get_iface_ip("eth0", eth0_ip) != 0) {
    fprintf(stderr, "Failed to get IP of eth0\n");
    return -1;
}

//绑定本地地址到eth0的对应IP
struct sockaddr_in local_addr;
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
//local_addr.sin_addr.s_addr = htonl(INADDR_ANY); //修改为如下
local_addr.sin_addr.s_addr = inet_addr(eth0_ip);  // 使用具体 IP
local_addr.sin_port = htons(port);
if (bind(sock, (struct sockaddr*)&local_addr, sizeof(local_addr)) < 0) {
    perror("bind");
    close(sock);
    return -1;
}

//加入组播时直接使用eth0的IP
struct ip_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr.s_addr = inet_addr("227.0.81.22");
inet_pton(AF_INET, eth0_ip, &mreq.imr_interface.s_addr);
//或直接赋值
//mreq.imr_interface.s_addr = inet_addr(eth0_ip);

if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
    perror("IP_ADD_MEMBERSHIP");
    close(sock);
    return -1;
}

// 设置接收超时(如果需要)
......

// 设置接收缓冲区大小(如果需要)
......

        3、绑定本地地址时的区别

        绑定本地地址时,可以选择绑定到 INADDR_ANY(通配所有接口)或绑定到 eth0 的特定 IP。两者都能工作,但区别在于:

        1、绑定到 INADDR_ANY:套接字可以接收发往本机任何 IP 地址(端口匹配)的 UDP 数据,包括组播和单播。组播数据只会从 eth0 加入的组播组到达。

        2、绑定到 eth0 的特定 IP:套接字只接收目标 IP 为该特定 IP 的数据,组播数据仍需通过加入组播组才能接收。这通常用于限制只接收来自该接口的流量。

二、相关函数和介绍

         1、setsockopt函数介绍

                a、setsockopt函数原型

#include <sys/socket.h>

int setsockopt(int sockfd, int level, int optname,
               const void *optval, socklen_t optlen);

                 b、setsockopt函数参数介绍

setsockopt函数参数介绍
sockfd套接字描述符,由 socket() 返回
level选项所属的协议层,决定 optname 的解释范围。常见值:
- SOL_SOCKET:通用套接字层
- IPPROTO_IP:IPv4 层
- IPPROTO_IPV6:IPv6 层
- IPPROTO_TCP:TCP 层

详细值见表:《常见level及optname》

optname具体的选项名称,依赖于 level详细值见表:《常见level及optname》
optval指向存放选项值的缓冲区。选项的数据类型取决于选项(可以是整数、结构体等)
optlenoptval 指向的数据长度(字节数)。通常用 sizeof(类型) 获得。
《常见level及optname》

 SOL_SOCKET 层(通用套接字选项)

选项名数据类型作用使用场景
SO_REUSEADDRint允许重用本地地址和端口,避免 bind 失败(如 TIME_WAIT 状态)。服务器快速重启、多实例绑定相同端口
SO_REUSEPORTint允许多个套接字绑定到同一端口,内核负载均衡分发数据。多进程/多线程服务器
SO_RCVBUFint设置接收缓冲区大小(字节)。提高接收能力,防止丢包
SO_SNDBUFint设置发送缓冲区大小。优化发送性能
SO_RCVTIMEOstruct timeval设置接收超时时间,recv/recvfrom 超时返回 -1,errno 为 EAGAIN/EWOULDBLOCK。避免无限阻塞
SO_SNDTIMEOstruct timeval设置发送超时时间。避免发送无限阻塞
SO_BROADCASTint允许发送广播消息(需先设置)。UDP 广播通信
SO_KEEPALIVEint开启 TCP 保活探测,检测连接是否存活。TCP 长连接
SO_LINGERstruct linger控制 close 关闭时如何处理未发送数据。确保数据发送完成或立即关闭
SO_DEBUGint开启调试信息(需内核支持)。开发调试

 IPPROTO_IP 层(IPv4 选项)

选项名数据类型作用使用场景
IP_ADD_MEMBERSHIPstruct ip_mreq加入组播组,指定组播地址和本地接口。接收组播数据
IP_DROP_MEMBERSHIPstruct ip_mreq离开组播组。停止接收组播数据
IP_MULTICAST_IFstruct in_addr设置组播数据发送的默认网络接口。指定从哪个网卡发送组播
IP_MULTICAST_TTLint设置组播数据包的生存时间(TTL)。默认 1,限制在本地子网。控制组播传播范围
IP_MULTICAST_LOOPint是否允许组播回环(本机发送的组播是否被本机接收)。0 禁止,1 允许。避免收到自己发送的组播
IP_TTLint设置单播数据包的 TTL。控制 IP 包跳数

IPPROTO_TCP 层(TCP 选项)

选项名数据类型作用使用场景
TCP_NODELAYint禁用 Nagle 算法,立即发送小数据包,减少延迟。实时性要求高的应用(如游戏、远程控制)
TCP_MAXSEGint获取或设置 TCP 最大分段大小(MSS)。优化传输性能
TCP_KEEPIDLEint保活探测开始前的空闲时间(秒)。调整 TCP 保活参数
TCP_KEEPINTVLint保活探测间隔(秒)。调整 TCP 保活参数
TCP_KEEPCNTint保活探测失败前最大尝试次数。调整 TCP 保活参数

        2、inet_ntop 函数和 inet_pton函数详解 

                a、函数原型

#include <arpa/inet.h>

// 将二进制地址转换为字符串(网络地址到表示形式)
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

// 将字符串转换为二进制地址(表示形式到网络地址)
int inet_pton(int af, const char *src, void *dst);
        参数说明:

  af:地址族,可选 AF_INET(IPv4)或 AF_INET6(IPv6)。    

  src:对于 inet_ntop,是指向存储二进制地址的缓冲区(例如 struct in_addr 或 struct in6_addr);对于 inet_pton,是指向要转换的字符串。

  dst:对于 inet_ntop,是存放转换后字符串的缓冲区;对于 inet_pton,是存放转换后二进制地址的缓冲区。

  size:仅用于 inet_ntop,指定 dst 缓冲区的大小(字节数),以避免缓冲区溢出。通常使用 INET_ADDRSTRLEN(IPv4)或 INET6_ADDRSTRLEN(IPv6)定义的大小。

        返回值:

inet_ntop:

        成功:返回指向 dst 的指针。

        失败:返回 NULL 并设置 errno。常见错误:

        EAFNOSUPPORT:af 不是有效的地址族。

        ENOSPC:size 指定的缓冲区太小。

inet_pton:

        成功:返回 1(地址有效且转换成功)。

        失败:若输入字符串不是有效的地址格式,返回 0(不设置 errno)。

        错误:返回 -1 并设置 errno,通常是因为 af 不支持。

                b、使用示例

                        IPV4转换

#include <stdio.h>
#include <arpa/inet.h>

int main() {
    struct in_addr addr4;          // 存储 IPv4 二进制地址
    char str[INET_ADDRSTRLEN];      // 足够大的缓冲区

    // 1. 将点分十进制字符串转换为二进制
    if (inet_pton(AF_INET, "192.168.1.1", &addr4) == 1) {
        printf("inet_pton success. Binary: 0x%08x\n", ntohl(addr4.s_addr));
    } else {
        printf("Invalid IPv4 address\n");
        return 1;
    }

    // 2. 将二进制转换回字符串
    if (inet_ntop(AF_INET, &addr4, str, sizeof(str)) != NULL) {
        printf("inet_ntop success. String: %s\n", str);
    } else {
        perror("inet_ntop");
        return 1;
    }

    return 0;
}

        输出: 

                inet_pton success. Binary: 0xc0a80101
                inet_ntop success. String: 192.168.1.1

                IPV6转换

#include <stdio.h>
#include <arpa/inet.h>

int main() {
    struct in6_addr addr6;
    char str[INET6_ADDRSTRLEN];

    // 1. 将 IPv6 字符串转换为二进制
    const char *ipv6_str = "2001:db8::1";
    if (inet_pton(AF_INET6, ipv6_str, &addr6) == 1) {
        printf("inet_pton success (IPv6)\n");
    } else {
        printf("Invalid IPv6 address\n");
        return 1;
    }

    // 2. 二进制转回字符串
    if (inet_ntop(AF_INET6, &addr6, str, sizeof(str)) != NULL) {
        printf("inet_ntop success: %s\n", str);
    } else {
        perror("inet_ntop");
        return 1;
    }

    return 0;
}

        输出:

                inet_pton success (IPv6)

                inet_ntop success: 2001:db8::1

注意:

        在 Windows 中,需要包含 ws2tcpip.h 并链接 Ws2_32.lib,且函数名相同,但可能需先调用 WSAStartup。

        在 POSIX 系统(Linux、macOS、BSD)中,直接包含 <arpa/inet.h> 即可

C语言组播实现 #include #include #include #include #include #include #include #include #define BUFLEN 255 #define GROUP_ADDR "229.0.0.211" #define GROUP_PORT 12345 int main(int argc, char **argv) { st 阅读详情

相关推荐

udp组播

udp组播udp组播先说明组播与广播 C语言实现客户端与服务端udp组播传递信息 监听端 发送端 先说明组播与广播可以参考的资料 Dake423大神的UDP 组播 广播 wiki的解释简单说就是下面这一句 组播是一对多的传输方式,发送端将数据向一个组内发送,网络中的路由器通过底层的IGMP协议自动将数据发送到所有监听这个组的终端。 至于广播则和组播有一些相似, 区别是路由器向子网内的每

lyblyblyblin的博客 987

C语言组播编程实战:从Socket选项到收发Demo与排坑指南

网络编程中,单播和广播难以兼顾效率与精确性,组播(Multicast)以“一对多订阅”模式成为局域网数据分发的重要方案。组播基于UDP,通过IGMP协议让主机动态加入组播组,网络设备据此按需转发,避免带宽浪费。在socket编程中,需正确设置IP_ADD_MEMBERSHIP、IP_MULTICAST_TTL等选项,才能实现可靠收发。该技术广泛用于设备发现、IPTV、实时行情等场景。本文用C语言演示组播收发Demo,并分享常见故障排查方法,帮助开发者快速掌握组播实战技能。

weixin_29611239的博客 254

【网络编程】组播的实现(C语言,linux,Ubuntu)

1> 组播也是实现一对多的通信方式,对于广播而言,网络需要对每个消息进行复制转发,会占用大量的带宽,导致网络拥塞2> 组播可以实现小范围的数据传播:将需要接收数据的接收端加入多播组,发送端向多播组中发送消息,每个组内成员都能接收到消息3> 需要对接收端进行设置,将接收端加入多播组1、需要使用setsockopt函数实现2、需要对网络层设置:IPPROTO_IP3、需要对加入多播组属性设置:IP_ADD_MEMBERSHIP4、属性值的类型。

m0_62859255的博客 866

UDP 组播/多播 C语言实现

目录 逻辑设计: 代码实现 运行结果 224.100.200.1 多播组 224.100.200.52多播组 思路: PC作为客户机,使用网络调试助手; LS开发板作为服务器端,部署对应程序(代码实现如下); 在UDP基本简单通信的基础上增加两组组播(setsockopt实现,一组也可以),实现组播通信; 运行服务器端程序,打开客户端向组播地址端口发送数据,此时服务器端将收到的数据发回客户端完成一次数据收发。 setsockopt 函数介绍见:https://blog.csdn.n.

动感超人_Crush 9540

在Window上安装和配置VTK9.x,并在QT项目中调试VTK是否可用

VTK+MSVC+Qt Creator + CMake配置

qq_42279379的博客 1000

手把手教你用Matlab/Simulink搭建PMSM的SMO无感FOC仿真(附相位补偿与离散化代码)

本文详细介绍了基于滑模观测器(SMO)的永磁同步电机(PMSM)无传感器FOC控制方法,通过Matlab/Simulink平台实现从理论到实践的完整流程。内容涵盖SMO核心原理、离散化处理、转子位置估算与相位补偿技术,以及双闭环控制系统搭建,为工程师提供了一套完整的无传感器控制解决方案。

weixin_27038245的博客 252

linux 下c语言同一组播地址udp通讯

欢迎使用Markdown编辑器写博客 UDP组播通讯可用 功能: 实现两台设备通过同一组播地址进行信息交互. 机器A 机器B 机器A发送指令,机器B接收指令 机器B回复一条报文 机器A 接收一条报文 机器A为发送方,客户端 机器B为接收端服务器端 发送端 Bind本地端口与IP,向组里发送数据,从本地接收数据。记得setsockopt加组与reuseaddr 机器B代码...

python基础 1367

freertos移植心得

1.freertos移植msp430 今天终于移植成功了freertos。现在写下这篇博文来整理这一路移植过程中遇到的问题和心得。 由于使用的是IAR FOR MSP430的IDE,博文只讨论在IAR下的移植。本文针对的是官方支持的平台架构下的移植,不使用官方提供的demo,得到的是一个纯洁版的系统。 1.下载源代码 在freertos的官网下载一份最新的源代码点击打开链接。 2.选择平

一条狗的博客 4172

linux下怎么使用C语言编写接收和发送udp组播数据?

一,发送端 代码如下: 先调用initUdpMultiCastSender初始化,   int initUdpMultiCastSender(uint32_t localip,uint16_t localport) { int sockfd = socket(AF_INET,SOCK_DGRAM,0); if (-1 == sockfd) { printf("[initUdpM...

yuhengyue的博客 8052

11-4 AEB 算法原理及系统组成

本专题旨在探讨如何利用仿真软件开发自动紧急制动系统AEB,主要通过整理开发流程,实现从需求到验证的全流程掌握,为后续开发提供支持;同时,研究了如何在汽车自动驾驶仿真工具中开发自己的算法,并解决了从ISO、E-CNAP、GB/T以及交通法规等提炼出功能需求的问题,以快速实现原型模型的开发。本专题重点讲解了AEB的工作原理、系统/软件架构和需求、算法模型及实现、CCRs/CCRb/CCRm建模与仿真、VRU-AEB-B/P/M建模与仿真,同时还提供了测试用例,期待将AEB算法成功地产品化。

AIgraphX 8548

一个超酷的开源uHand2.0机械手掌项目

uHand2.0是深圳乐幻索尔公司开源的一款机械手掌,它长下面这个样子:1、uHand2.0外观图之前在公众号就分享过视频:学习嵌入式可以带娃,不信你们看2、uHand2.0硬件原理图看...

Bruce.yang的嵌入式之旅 4458

linux查看发出去的组播信息,linux下怎么使用C语言编写接收和发送udp组播数据?...

一,发送端代码如下:先调用initUdpMultiCastSender初始化,int initUdpMultiCastSender(uint32_t localip,uint16_t localport){int sockfd = socket(AF_INET,SOCK_DGRAM,0);if (-1 == sockfd){printf("[initUdpMultiCastSender]socke...

weixin_39688687的博客 245

27930-2015+充电协议解析

对2015+充电与2015充电进行硬件电路对比、通信协议对比和2015+通信协议解析。

manjixingkong1234的专栏 232

Linux 多播(组播)例程

本例程修改自:http://zhoulifa.bokee.com/6066993.html 博文提供的例程。 ser.c  #include #include #include #include #include #include string.h> #include #include #define BUFLEN 255 int main

nickol51的专栏 1012

第5.2章 【自动驾驶行业融合定位核心】:手把手详解ESKF(误差卡尔曼滤波)理论公式及代码

自动驾驶定位中的ESKF(误差卡尔曼滤波)技术是解决IMU累积误差的关键,通过分离名义状态与误差状态实现高精度定位。其核心步骤包括:1)名义状态递推(位置/速度/姿态的基础物理计算);2)误差传播建模(雅可比矩阵F量化误差影响);3)协方差更新(评估定位不确定性)。ESKF在GNSS信号丢失(如隧道场景)、无卫星定位(地下车库)等场景发挥重要作用,通过融合多传感器数据维持定位精度。工程实现需解决零偏校准、协方差投影等关键问题,噪声参数需通过数据标定而非随意设置。掌握ESKF原理与实现是自动驾驶定位工程师的核

行知SLAM 703

OpenAI Error: 403 Country, region, or territory not supported [Python]

从OpenAI的API服务中获取数据时,由于你所在的国家、地区或领土不被支持,因此请求被拒绝了

suiusoar 5662

C语言使用多播/组播IP_ADD_MEMBERSHIP出现Invalid argument错误解决方法

C语言使用组播IP_ADD_MEMBERSHIP出现Invalid argument错误的解决方法

qq_42938839的博客 2163

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

UDP组播接收端的绑定问题bind(),IP_ADD_MEMBERSHIP

UDP组播接收的代码如下: struct sockaddr_in localSock; struct ip_mreq group; int sd; int datalen; char databuf[1024]; int main (int argc, char *arg...

photon222的博客 8985

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

组播原理及 C语言编程

源自:http://blog.163.com/mh_333333333/blog/static/3585491220095199419684/ 摘要:     本文可做为TCP/IP组播技术的入门材料,文中介绍了组播通信的概念及原理,以及用于组播应用编程的Linux API的详细资料。为了使读者更加完整的了解Linux 组播的整体概念,文中对实现该技术的核心函数也做了介绍。在文章的最后给出

xiaowen_10的专栏 9520

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Linux组播代码

Ubuntu组播 在真机上没有问题,但是放到虚拟机里面,使用桥接方式,就接收不到组播包了,需要手动添加组播路由: sudo add -net 239.255.255.0 netmask 255.255.255.0 dev eth0 相应代码: #include <stdio.h> #include <unistd.h> #include <string.h>...

rbin_yao的博客 818

Linux C:简单udp组播,服务器端代码实现

udp广播跟组播实现差不多,但是广播只能在局域网下,而多播(组播)也可以在广域网下使用。这次分享的是组播的服务器代码。 主要流程:创建套接字-》绑定服务器端口-》开放服务器广播权限-》创建广播地址段的客户端-》开始在这个网段广播 客户端只要加入这个对应端口和网段就可以收到组播的内容了 #include <stdio.h> #include <stdlib.h> #inclu...

凝视阳光呦 3047

组播 笔记

文章目录简述单播组播发送Python组播接收PythonC组播接收C组播发送参考 简述 SOME/IP用到了组播, 如华为MDC300F系统101版本的SOME/IP组播域地址为239.192.255.251, 端口号 30491. 本篇不讲SOME/IP, 只看下组播的概念. 组播(Multicast, 又称多播)是UDP专有的, 关于UDP的单播(Unicast), 组播, 广播(Broadcast)的区别, 网络上有张图有些形象: D类地址空间分配给了IP组播, 范围 224.0.0.0~239.2

weifengdq的专栏 2175

组播例子

编译程序用下列命令: gcc -Wall mcastclient.c -o mcastclient gcc -Wall mcastserver.c -o mcastserver 运行程序用如下命令: ./mcastserver 230.1.1.1 7838 客户端程序运行命令为: ./mcastclient 230.1.1.1 7838 192.168.100.1 12345 */

L_yangliu的专栏 1065

组播通信

摘要:      本文试图成为学习TCP/IP网络组播技术的入门材料。文中介绍了组播通信的概念及原理,以及用于组播应用编程的Linux API的详细资料。为了使读者更加完整的了解Linux组播的整体概念,文中对实现该技术的核心函数也做了介绍。在文章的最后给出了一个简单的C语言套接字编程例子,说明如何创建组播应用程序。      一、导言      在网络中,主机间可

sdlcgxcqx的专栏 1195
上一篇: QNetworkInterface类介绍
下一篇: ESP32 Arduino 框架中 Preferences 类的使用指导:函数讲解与实战示例
西装没钱买
博客等级 码龄4年 620粉丝 52原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值