欢迎光临
我们一直在努力

29 鸿蒙LiteOS RK2206 Socket编程实战 UDP通信+LWIP原理全解析

鸿蒙LiteOS RK2206 Socket编程实战 UDP通信+LWIP原理全解析

B站 配套视频教程【鸿蒙 LiteOS 实战 15】LwIP socket API UDP通信 客户端

前言

在鸿蒙LiteOS(以瑞芯微RK2206为例)开发中,Socket网络编程是设备联网通信的核心技能,无论是设备与服务器数据交互、MQTT传输还是UDP广播控制,都离不开标准Socket接口与LWIP轻量级网络协议栈。

本文基于RK2206官方Demo源码,从零讲解Socket基础、阻塞通信特性、UDP协议原理,同时拆解LiteOS网络组件LWIP的底层逻辑,带你彻底掌握嵌入式设备的UDP客户端开发。

本文主要目标:

  • 什么是Socket,如何写标准Socket程序
  • 什么是阻塞通信,如何从日志观察阻塞
  • UDP 协议通信原理与实战
  • LiteOS 网络组件从哪里来(LWIP)

  • 一、什么是Socket?标准Socket程序怎么写?

    1. Socket 核心概念

    Socket(套接字) 是计算机网络中进程间通信的端点,可以理解为网络通信的"插座":两个设备想要通信,必须各自创建一个Socket,通过IP地址+端口号唯一标识,然后基于Socket完成数据的发送与接收。

    简单来说:Socket = IP地址 + 端口号,它屏蔽了底层网络协议的复杂细节,为上层应用提供统一的读写接口。

    2. 标准Socket程序通用框架

    无论Windows、Linux还是嵌入式LiteOS,标准Socket编程流程完全一致,分为TCP和UDP两种模式,本文重点讲UDP(无连接) 模式。

    UDP Socket 标准编程流程(客户端)

    1. 创建Socket → socket()
    2. 配置服务器地址(IP+端口)
    3. 发送数据 → sendto()
    4. 接收数据 → recvfrom()
    5. 关闭Socket → close()

    对应本文代码核心实现

    // 1. 创建UDP Socket(SOCK_DGRAM表示UDP协议)
    int fd = socket(AF_INET, SOCK_DGRAM, 0);

    // 2. 配置服务器地址
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET; // 地址族:IPv4
    server_addr.sin_addr.s_addr = inet_addr(IP);// 服务器IP
    server_addr.sin_port = htons(PORT); // 服务器端口(主机字节序转网络字节序)

    // 3. 发送数据
    sendto(fd, buf, strlen(buf), 0, (struct sockaddr *)&server_addr, len);

    // 4. 接收数据
    recvfrom(fd, buf, BUFF_LEN, 0, (struct sockaddr *)&server_addr, &len);

    // 5. 关闭Socket
    lwip_close(fd);

    关键函数说明

  • socket(AF_INET, SOCK_DGRAM, 0):
    • AF_INET:IPv4协议;
    • SOCK_DGRAM:UDP数据报协议(TCP对应SOCK_STREAM);
    • 返回值:Socket文件描述符(负数表示创建失败)。
  • htons():主机字节序转网络字节序(网络传输统一用大端序)。
  • sendto()/recvfrom():UDP专用收发函数,无需建立连接,直接指定目标地址收发数据。

  • 二、什么是阻塞通信?如何从日志观察阻塞?

    1. 阻塞通信定义

    阻塞通信:当程序调用阻塞函数时,内核会挂起当前线程,直到函数执行完成(收到数据/超时/出错)才会继续执行后续代码。

    简单理解:线程会"卡住"等待,不完成不往下走。

    本文UDP代码中,recvfrom()就是典型的阻塞函数:

    • 当服务器没有发送数据时,线程会停在recvfrom()这一行,一直等待数据到来;
    • 只有收到数据、函数返回后,才会执行后续的LOS_Msleep(1000)。

    2. 阻塞通信的特点

  • 编程简单,逻辑直观;
  • 线程资源占用低(阻塞时内核不调度);
  • 适合简单的同步通信场景(本文UDP客户端)。
  • 3. 如何从日志观察阻塞?

    结合本文代码,通过串口日志可以清晰看到阻塞行为:

    # 正常收发日志(无阻塞等待)
    [Send] RK2206 UDP Client msg: 1
    [Recv] Server reply: hello
    [Send] RK2206 UDP Client msg: 2
    [Recv] Server reply: hello

    # 服务器未回复时(阻塞现象)
    [Send] RK2206 UDP Client msg: 3
    # 这里会停顿!线程阻塞在recvfrom(),无任何日志输出
    # 直到服务器发送数据,才会打印[Recv]

    观察关键点:

    • 发送完数据后,长时间没有接收日志 → 线程阻塞在recvfrom();
    • 一旦服务器回复,立即打印接收日志 → 阻塞解除,线程恢复执行。

    扩展:非阻塞通信

    如果不想让线程卡住,可以将Socket设置为非阻塞模式:

    // 获取Socket当前状态
    int flags = fcntl(fd, F_GETFL, 0);
    // 设置为非阻塞
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);

    非阻塞模式下,recvfrom()无数据时会立即返回-1,不会挂起线程。


    三、UDP协议通信原理与实战(基于本文代码)

    1. UDP 协议核心原理

    UDP(User Datagram Protocol,用户数据报协议) 是无连接、不可靠、轻量级的传输层协议,核心特点:

  • 无需建立连接:不像TCP需要三次握手,直接发送数据报;
  • 不可靠传输:不保证数据一定到达,不保证顺序;
  • 面向数据报:数据按包发送,包与包之间独立;
  • 速度快、开销小:适合视频、直播、传感器实时数据传输。
  • 2. UDP 与 TCP 核心区别

    特性UDPTCP
    连接性 无连接 面向连接(三次握手)
    可靠性 不可靠 可靠(重传、确认)
    传输效率
    适用场景 实时通信、广播、组播 文件传输、可靠通信

    3. 本文UDP客户端实战解析

    本文代码是标准的LiteOS UDP客户端,完整实现了「WiFi联网→UDP循环收发」功能,核心逻辑拆解:

    (1)等待WiFi联网(前置条件)

    // 循环等待WiFi连接成功+获取到IP地址
    while (udp_get_wifi_info(&g_wifiinfo) != 0)
    {
    LOS_Msleep(1000);
    }

    • 嵌入式设备必须先联网(获取IP),才能进行Socket通信;
    • GetLinkedInfo()是RK2206 WiFi驱动接口,获取连接状态和IP。
    (2)UDP循环收发

    while (1)
    {
    // 1. 发送数据到服务器
    sprintf(buf, "RK2206 UDP Client msg: %d \\r\\n", cnt++);
    sendto(fd, buf, strlen(buf), 0, (struct sockaddr *)&server_addr, len);

    // 2. 阻塞等待服务器回复
    count = recvfrom(fd, buf, BUFF_LEN, 0, (struct sockaddr *)&server_addr, &len);

    LOS_Msleep(1000);
    }

    • 每秒发送一条自定义消息到指定服务器;
    • 阻塞等待服务器回复,收到后打印数据;
    • 全程无连接,断电、断网重连后可直接恢复通信。
    (3)测试方法
  • 修改代码中3个核心参数:

    #define OC_SERVER_IP "192.168.111.61" // 电脑端服务器IP
    #define SERVER_PORT 20108 // 服务器端口
    #define CLIENT_LOCAL_PORT 8888 // 本地端口

  • 电脑打开网络调试助手,创建UDP服务器;

  • 烧录程序到RK2206,WiFi联网后即可看到双向通信日志。

  • 在这里插入图片描述


    四、LiteOS网络组件从哪里来?LWIP协议栈全解析

    1. 为什么嵌入式要用LWIP?

    PC端的网络协议栈庞大复杂,占用大量内存,嵌入式设备(MCU、IoT芯片)资源有限,无法直接使用。

    因此嵌入式领域通用LWIP(Light Weight IP) 轻量级网络协议栈:

    • 开源、免费、体积小;
    • 支持TCP/UDP/IP/ARP等完整网络协议;
    • 内存占用极低,适合单片机、IoT设备;
    • 鸿蒙LiteOS、FreeRTOS、RT-Thread全部内置LWIP。

    2. 本文代码中的LWIP

    代码开头的头文件,全部来自LWIP协议栈:

    #include "lwip/udp.h"
    #include "lwip/ip_addr.h"
    #include "lwip/priv/tcp_priv.h"
    #include "lwip/stats.h"
    #include "lwip/inet_chksum.h"

    我们调用的socket()/sendto()/recvfrom(),本质是LWIP对外封装的标准POSIX接口,底层由LWIP实现网络数据的打包、发送、解析。

    3. LWIP在LiteOS中的架构

    应用层 → 标准Socket接口(sendto/recvfrom)

    LWIP协议栈 → 处理TCP/UDP/IP协议

    网卡驱动 → WiFi/以太网硬件驱动

    硬件层 → RK2206 WiFi模块

    4. LiteOS中LWIP的核心作用

  • 实现标准Socket API,让开发者像写Linux网络程序一样写嵌入式网络代码;
  • 管理网络连接、IP地址、端口、数据缓存;
  • 完成数据的封装与解包(IP头、UDP头、校验和);
  • 与底层硬件驱动交互,实现数据的物理收发。
  • 简单说:LWIP就是LiteOS的"网络心脏",没有它,嵌入式设备无法实现TCP/IP通信。


    五、完整代码说明

    本文提供的代码是RK2206鸿蒙LiteOS UDP客户端完整可运行代码,仅需修改3个参数即可直接使用:

  • 服务器IP;
  • 服务器端口;
  • 本地端口。
  • 代码特性:

    • 开机自动启动(APP_FEATURE_INIT);
    • 自动等待WiFi联网成功;
    • 阻塞式UDP循环收发,1秒发送一次;
    • 串口打印收发日志,方便调试。

    六、总结

  • Socket是网络通信的端点,嵌入式UDP Socket遵循「创建→配置地址→收发→关闭」标准流程;
  • 阻塞通信是线程等待函数执行完成,通过串口日志可观察到"停顿"现象,编程简单;
  • UDP是无连接、轻量级协议,适合实时性要求高的场景,无需建立连接直接收发数据;
  • LWIP是LiteOS内置的轻量级网络协议栈,是嵌入式设备联网的核心组件,提供标准Socket接口。
  • 本文基于RK2206实战Demo,从基础到原理全覆盖,适合鸿蒙LiteOS、嵌入式网络编程新手学习,替换IP和端口即可直接用于项目开发。

    赞(0)
    未经允许不得转载:171主机测评 » 29 鸿蒙LiteOS RK2206 Socket编程实战 UDP通信+LWIP原理全解析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址