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客户端开发。

本文主要目标:

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

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

1. Socket 核心概念

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

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

2. 标准Socket程序通用框架

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

UDP Socket 标准编程流程(客户端)
复制代码
1. 创建Socket → socket()
2. 配置服务器地址(IP+端口)
3. 发送数据 → sendto()
4. 接收数据 → recvfrom()
5. 关闭Socket → close()
对应本文代码核心实现
c 复制代码
// 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);

关键函数说明

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

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

1. 阻塞通信定义

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

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

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

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

2. 阻塞通信的特点

  1. 编程简单,逻辑直观;
  2. 线程资源占用低(阻塞时内核不调度);
  3. 适合简单的同步通信场景(本文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设置为非阻塞模式

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

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


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

1. UDP 协议核心原理

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

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

2. UDP 与 TCP 核心区别

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

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

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

(1)等待WiFi联网(前置条件)
c 复制代码
// 循环等待WiFi连接成功+获取到IP地址
while (udp_get_wifi_info(&g_wifiinfo) != 0)
{
    LOS_Msleep(1000);
}
  • 嵌入式设备必须先联网(获取IP),才能进行Socket通信;
  • GetLinkedInfo()是RK2206 WiFi驱动接口,获取连接状态和IP。
(2)UDP循环收发
c 复制代码
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)测试方法
  1. 修改代码中3个核心参数:

    c 复制代码
    #define OC_SERVER_IP "192.168.111.61" // 电脑端服务器IP
    #define SERVER_PORT 20108             // 服务器端口
    #define CLIENT_LOCAL_PORT 8888        // 本地端口
  2. 电脑打开网络调试助手,创建UDP服务器;

  3. 烧录程序到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协议栈

c 复制代码
#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的核心作用

  1. 实现标准Socket API,让开发者像写Linux网络程序一样写嵌入式网络代码;
  2. 管理网络连接、IP地址、端口、数据缓存;
  3. 完成数据的封装与解包(IP头、UDP头、校验和);
  4. 与底层硬件驱动交互,实现数据的物理收发。

简单说:LWIP就是LiteOS的"网络心脏",没有它,嵌入式设备无法实现TCP/IP通信。


五、完整代码说明

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

  1. 服务器IP;
  2. 服务器端口;
  3. 本地端口。

代码特性:

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

六、总结

  1. Socket是网络通信的端点,嵌入式UDP Socket遵循「创建→配置地址→收发→关闭」标准流程;
  2. 阻塞通信是线程等待函数执行完成,通过串口日志可观察到"停顿"现象,编程简单;
  3. UDP是无连接、轻量级协议,适合实时性要求高的场景,无需建立连接直接收发数据;
  4. LWIP是LiteOS内置的轻量级网络协议栈,是嵌入式设备联网的核心组件,提供标准Socket接口。

本文基于RK2206实战Demo,从基础到原理全覆盖,适合鸿蒙LiteOS、嵌入式网络编程新手学习,替换IP和端口即可直接用于项目开发。

相关推荐
小雨下雨的雨3 小时前
HarmonyOS V2状态管理深度解析:列表数据与分页架构
华为·架构·harmonyos·鸿蒙
YM52e14 小时前
男孩子在外自我保护指南——用鸿蒙 ArkTS 构建交互式安全教育应用
学习·安全·华为·harmonyos·鸿蒙·鸿蒙系统
三声三视16 小时前
Electron 本地图片在鸿蒙 PC 上白图,我注册了个自定义协议
electron·harmonyos·鸿蒙
AI_零食1 天前
HarmonyOS ArkTS 设计系统构建实战指南
学习·华为·harmonyos·鸿蒙·鸿蒙系统
AI_零食1 天前
HarmonyOS ArkTS 常用工具函数实现与应用详解
华为·开源·harmonyos·鸿蒙·鸿蒙系统
艾莉丝努力练剑1 天前
【Linux网络】数据链路层协议(二):ARP协议
linux·运维·服务器·网络·计算机网络·udp
AI_零食1 天前
HarmonyOS 表单验证机制深度解析与实践
学习·华为·harmonyos·鸿蒙·鸿蒙系统
AI_零食1 天前
HarmonyOS ArkTS 类型转换机制深度解析
学习·华为·harmonyos·鸿蒙
带土11 天前
12. UDP协议概述
网络·网络协议·udp