基于小智派-LZ3863星闪开发板:OpenHarmony WiFi 网络开发 — TCP 服务端
2026/8/1 17:19:18 网站建设 项目流程

1、实验简介

参考网址:https://gitee.com/Lockzhiner-Electronics/lz3863/tree/master/apps/c3_wifi_tcp_server

1.1、实验目的

本实验旨在帮助学习者掌握 OpenHarmony 轻量系统中WiFi + TCP 服务端的基本使用方法。通过本实验,你将学会:

  1. 理解TCP 协议的面向连接、可靠传输特性及客户端/服务端通信模型;
  2. 在开发板上以 STA 模式连接 WiFi 热点,通过 DHCP 获取 IP 地址;
  3. 使用 lwIPSocket API创建 TCP 服务端,完成绑定、监听、接受连接与数据收发;
  4. 掌握 TCP 服务端与客户端的完整联调流程;
  5. 完成案例代码的编译、烧录与串口现象观察。

1.2、实验内容

本案例在 LZ3863-星闪开发板上实现TCP 服务端功能:先连接指定 WiFi 热点并获取 IP,再在本机端口上创建 TCP 服务、等待客户端连接,连接建立后发送初始测试数据并持续接收客户端数据,全过程通过串口打印日志。

项目说明
源文件wifi_tcp_server_example.c(主程序)、wifi_connecter.c(WiFi 封装)
WiFi 模式STA(站点/客户端)
目标 SSIDlzdz
目标密码88888888
TCP 监听端口777
绑定地址INADDR_ANY(接受任意 IP 的客户端连接)
发送测试数据wifi_tcp_test_date
任务线程tcp_server_demo_task(栈大小 8192 字节)
初始化入口APP_FEATURE_INIT(tcp_server_demo_entry)

典型联调拓扑:

┌─────────────────┐ WiFi ┌─────────────────┐ │ PC / 手机热点 │ ◄──────────────────► │ LZ3863 开发板 │ │ SSID: lzdz │ │ (TCP Server) │ │ │ TCP :777 │ IP: 192.168. │ │ (TCP Client) │ ◄──────────────────► │ 137.x │ └─────────────────┘ └─────────────────┘

说明:开发板作为 TCP 服务端,需先通过串口日志确认其 DHCP 获取到的 IP 地址,客户端(PC 网络调试工具、nc命令或c2_wifi_tcp_client案例)应连接该 IP 及端口777

1.3、实验环境

项目说明
硬件LZ3863-星闪开发板、USB 数据线
软件OpenHarmony v5.1.0 源码、hb 编译工具
网络环境可连接的 WiFi 热点(SSID/密码与代码一致)
TCP 客户端PC 端网络调试工具 /nc/ Python 脚本,或c2_wifi_tcp_client案例
调试工具串口助手(波特率 115200,8N1)
案例路径applications/sample/wifi-iot/app/c3_wifi_tcp_server/

2、基础知识

2.1、TCP 协议概述

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的传输层协议,具有以下特点:

特性说明
面向连接通信前需通过三次握手建立连接,结束后四次挥手断开
可靠传输通过序号、确认、重传机制保证数据不丢失、不重复
全双工连接建立后,双方可同时发送和接收数据
字节流数据以连续字节流形式传输,无固定报文边界

TCP 通信采用客户端/服务端(C/S)模型:

角色职责本实验对应
TCP 服务端绑定端口、监听连接、接受客户端请求本案例开发板
TCP 客户端主动发起连接、发送/接收数据PC 或另一块开发板

2.2、Socket 服务端编程基础

Socket(套接字)是网络编程的抽象接口,lwIP 提供了与 BSD Socket 兼容的 API。TCP 服务端的典型流程:

socket() → 创建套接字 ↓ 配置 sockaddr_in(INADDR_ANY + 端口) ↓ bind() → 绑定本地 IP 和端口 ↓ listen() → 进入监听状态 ↓ accept() → 阻塞等待客户端连接(三次握手) ↓ send() / recv() → 与客户端收发数据 ↓ closesocket() → 关闭连接

与 TCP 客户端的关键区别:

步骤TCP 客户端TCP 服务端(本实验)
地址配置指定服务器 IP + 端口INADDR_ANY+ 监听端口
建立连接connect()主动连接bind()+listen()+accept()被动等待
通信对象使用同一sockfd监听套接字sockfd+ 连接套接字connfd

关键数据结构sockaddr_in(服务端):

structsockaddr_inserver_addr={0};server_addr.sin_family=AF_INET;// IPv4server_addr.sin_port=htons(port);// 端口号(转网络字节序)server_addr.sin_addr.s_addr=htonl(INADDR_ANY);// 绑定所有网卡,接受任意 IP 接入

字节序转换:

函数作用
htons()主机字节序 → 网络字节序(16 位,用于端口)
htonl()主机字节序 → 网络字节序(32 位,用于 IP)
inet_ntoa()二进制网络地址 → 字符串 IP(用于打印客户端地址)
ntohs()网络字节序 → 主机字节序(16 位,用于端口)

2.3、WiFi STA 连接与网络层

本案例在启动 TCP 服务之前,需先通过ConnectToHotspot()完成 WiFi 连接与 IP 获取。完整流程为:

启用 STA 模式 → 扫描热点 → 匹配 SSID → 关联连接 → 启动 DHCP 客户端 → 获取 IP 地址 → 网络层就绪

获取 IP 后,开发板与 TCP 客户端处于同一局域网,客户端可通过该 IP 地址和监听端口发起连接。

2.4、软件调用层次

本案例的软件调用层次如下:

应用层(wifi_tcp_server_example.c) ├── tcp_server_demo_entry() ← APP_FEATURE_INIT 注册入口 ├── tcp_server_demo_task() ← 任务线程:WiFi 连接 + TCP 服务端 └── tcp_server_test() ← TCP 核心逻辑 │ WiFi 封装层(wifi_connecter.c) └── ConnectToHotspot() ← 扫描、连接、DHCP 获取 IP │ 协议栈 / 驱动层 ├── lwIP Socket API(socket/bind/listen/accept/send/recv) ├── lwIP 网络协议栈(TCP/IP、DHCP) └── WiFi 驱动(HMAC/DMAC)

2.5、核心 API 介绍

2.5.1、头文件
#include"cmsis_os2.h"#include"lwip/sockets.h"#include"ohos_init.h"#include"osal_debug.h"#include"wifi_connecter.h"#include<errno.h>#include<stdio.h>#include<string.h>#include<unistd.h>
2.5.2、Socket API(服务端)
API 名称功能说明
socket(AF_INET, SOCK_STREAM, 0)创建 IPv4 TCP 套接字,返回套接字描述符
bind(sockfd, addr, addrlen)将套接字绑定到指定的 IP 地址和端口
listen(sockfd, backlog)使套接字进入监听状态,等待客户端连接
accept(sockfd, addr, addrlen)阻塞等待并接受客户端连接,返回新的连接套接字
send(sockfd, buf, len, flags)向已连接套接字发送数据,返回实际发送字节数
recv(sockfd, buf, len, flags)从已连接套接字接收数据,返回实际接收字节数
closesocket(sockfd)关闭套接字,释放资源
inet_ntoa(in_addr)将网络字节序 IP 地址转换为字符串
2.5.3、WiFi 与应用层 API
API 名称功能说明
ConnectToHotspot(ssid, password)扫描并连接指定热点,完成 DHCP 获取 IP
DisconnectWithHotspot()停止 DHCP 并断开 WiFi 连接
osThreadNew(func, arg, &attr)创建 RTOS 线程
osDelay(ticks)线程延时,100 ticks ≈ 1 秒(tick = 10 ms)
APP_FEATURE_INIT(func)注册应用特性初始化入口,系统启动后自动执行

3、程序设计

3.1、程序架构

本案例目录结构

c3_wifi_tcp_server/ ├── wifi_tcp_server_example.c # TCP 服务端主程序 ├── wifi_connecter.c # WiFi 连接封装实现 ├── wifi_connecter.h # 封装接口头文件 ├── BUILD.gn # GN 编译配置 ├── README_zh.md # 案例简要说明 └── 实验手册.md # 本实验手册

程序执行流程:

系统启动 │ ▼ tcp_server_demo_entry() ← APP_FEATURE_INIT 注册,自动执行 │ ▼ osThreadNew(tcp_server_demo_task) ← 创建 TCP 服务端任务线程 │ ▼ tcp_server_demo_task() ├── ConnectToHotspot() ← 连接 WiFi 热点,DHCP 获取 IP ├── osDelay(800) ← 等待网络稳定(约 8 秒) └── tcp_server_test() ← 启动 TCP 服务端 ├── socket() ← 创建套接字 ├── bind() ← 绑定端口 777 ├── listen() ← 进入监听状态 ├── accept() ← 等待客户端连接 ├── send() ← 向客户端发送初始数据 ├── recv() 循环 ← 持续接收客户端数据 └── closesocket() ← 关闭连接

3.2、源文件说明

文件说明
wifi_tcp_server_example.cTCP 服务端主程序,包含 WiFi 连接、TCP 服务及任务线程
wifi_connecter.cWiFi 封装,实现ConnectToHotspotStartHotspotDisconnectWithHotspot
wifi_connecter.h封装接口声明
BUILD.gn编译配置,生成wifi_tcp_server_example静态库

3.3、关键代码分析

(1)WiFi 与 TCP 配置参数
#defineWIFI_SSID"lzdz"#defineWIFI_PASSWORD"88888888"#defineTCP_SERVER_PORT777staticcharsend_data[50]="wifi_tcp_test_date";staticcharrecv_data[100];

实验前请根据实际网络环境修改WIFI_SSIDWIFI_PASSWORD,确保与可用热点一致。TCP 监听端口可通过TCP_SERVER_PORT修改。

(2)系统入口 — tcp_server_demo_entry

通过APP_FEATURE_INIT注册应用入口,创建tcp_server_demo_task线程:

staticvoidtcp_server_demo_entry(void){osThreadAttr_tattr={.name="tcp_server_demo_task",.stack_size=8192,.priority=osPriorityNormal};if(osThreadNew(tcp_server_demo_task,NULL,&attr)==NULL){printf("[tcp_server_demo_entry] Failed to create tcp_server_demo_task!\r\n");}}APP_FEATURE_INIT(tcp_server_demo_entry);
(3)任务线程 — tcp_server_demo_task

任务线程先完成 WiFi 连接,延时等待网络稳定后再启动 TCP 服务端:

staticvoidtcp_server_demo_task(void*arg){(void)arg;printf("Starting Wi-Fi connection to SSID: %s...\r\n",WIFI_SSID);if(ConnectToHotspot(WIFI_SSID,WIFI_PASSWORD)!=0){printf("Failed to connect to AP.\r\n");return;}printf("Wi-Fi connected successfully.\r\n");osDelay(800);// 等待约 8 秒,确保网络栈稳定tcp_server_test(TCP_SERVER_PORT);}
(4)TCP 服务端核心 — tcp_server_test

tcp_server_test()实现完整的 TCP 服务端通信流程:

voidtcp_server_test(unsignedshortport){ssize_tret=0;intbacklog=1;// 1. 创建 TCP 套接字intsockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd<0){printf("Failed to create socket! errno=%d\r\n",errno);return;}intconnfd=-1;structsockaddr_inclient_addr={0};socklen_tclient_addr_len=sizeof(client_addr);structsockaddr_inserver_addr={0};// 2. 配置服务端地址(绑定所有网卡)server_addr.sin_family=AF_INET;server_addr.sin_port=htons(port);server_addr.sin_addr.s_addr=htonl(INADDR_ANY);// 3. 绑定端口ret=bind(sockfd,(structsockaddr*)&server_addr,sizeof(server_addr));if(ret<0){printf("Bind to port %d failed! errno=%d\r\n",port,errno);closesocket(sockfd);return;}printf("Bind to port %d success!\r\n",port);// 4. 进入监听状态ret=listen(sockfd,backlog);if(ret<0){printf("Listen on port %d failed! errno=%d\r\n",port,errno);closesocket(sockfd);return;}printf("Listen with %d backlog success!\r\n",backlog);// 5. 阻塞等待客户端连接connfd=accept(sockfd,(structsockaddr*)&client_addr,&client_addr_len);if(connfd<0){printf("Accept connection failed! errno=%d\r\n",errno);closesocket(sockfd);return;}printf("Accepted connection, connfd=%d\r\n",connfd);printf("Client info: IP=%s, Port=%d\r\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));// 6. 向客户端发送初始数据ret=send(connfd,send_data,strlen(send_data),0);if(ret<0){printf("Send data to client failed! errno=%d\r\n",errno);}else{printf("Sent data{%s} %ld bytes to client!\r\n",send_data,ret);}// 7. 持续接收客户端数据while(1){memset(recv_data,0,sizeof(recv_data));ret=recv(connfd,recv_data,sizeof(recv_data)-1,0);if(ret<=0){printf("Recv data failed or connection closed! ret=%ld, errno=%d\r\n",ret,errno);break;}recv_data[ret]='\0';printf("Received data{%s} from client!\r\n",recv_data);osDelay(100);// 防止忙等待}// 8. 关闭套接字closesocket(connfd);closesocket(sockfd);}

设计要点:

  • INADDR_ANY表示绑定到所有可用网卡,客户端可通过开发板的任意 IP 地址连接;
  • backlog = 1表示等待队列最多容纳 1 个未完成连接;
  • accept()返回的connfd用于与客户端通信,原sockfd仍用于监听(本案例仅处理一个客户端);
  • recv()返回 0 表示客户端正常关闭连接,返回负值表示出错。
(5)WiFi 封装层 — ConnectToHotspot 概要

ConnectToHotspot()wifi_connecter.c中实现,主要步骤:

  1. 调用wifi_sta_enable()启用 STA 模式;
  2. 循环执行wifi_sta_scan()扫描,get_match_network()匹配目标 SSID;
  3. 调用wifi_sta_connect()发起关联,等待WIFI_CONNECTED状态;
  4. wlan0接口上启动 DHCP 客户端,获取 IP 地址并打印。

3.4、程序执行流程

TCP 客户端 (PC/开发板)WiFi 热点开发板 (TCP Server)TCP 客户端 (PC/开发板)WiFi 热点开发板 (TCP Server)连接关闭或出错时 closesocket()APP_FEATURE_INIT → tcp_server_demo_entryosThreadNew(tcp_server_demo_task)ConnectToHotspot("lzdz")关联成功 + DHCP 分配 IPosDelay(800) 等待网络稳定bind(:777) + listen()connect(开发板IP:777)accept() 三次握手完成send("wifi_tcp_test_date")客户端发送数据recv() 循环打印接收内容

4、编译步骤

以下步骤只需在首次编译时完成 4.1~4.3 的配置注册。

4.1、确认案例目录

确认案例已位于 OpenHarmony 源码目录下:

applications/sample/wifi-iot/app/c3_wifi_tcp_server/ ├── wifi_tcp_server_example.c ├── wifi_connecter.c ├── wifi_connecter.h ├── BUILD.gn └── 实验手册.md

若从外部复制,请将c3_wifi_tcp_server目录放到上述app/路径下。

4.2、修改 BUILD.gn(注册编译组件)

编辑applications/sample/wifi-iot/app/BUILD.gn,在features列表中添加本案例:

lite_component("app") { features = [ "startup", "c3_wifi_tcp_server:wifi_tcp_server_example", // 添加此行 ] }

4.3、修改 SDK 配置文件

步骤 1:编辑device/soc/hisilicon/ws63v100/sdk/build/config/target_config/ws63/config.py

找到'ws63-liteos-app'配置段,在其'ram_component'列表中添加:

"wifi_tcp_server_example"

步骤 2:编辑device/soc/hisilicon/ws63v100/sdk/libs_url/ws63/cmake/ohos.cmake

找到"ws63-liteos-app"对应的set(COMPONENT_LIST部分,添加:

"wifi_tcp_server_example"

4.4、编译固件

在 OpenHarmony 源码根目录下执行编译:

rm-rfout hbset-root.# 通过上下方向键选择 ws63 对应的编译分支(如 nearlink_dk_3863 / ws63-liteos-app)hb build-f

编译成功后,使用开发板配套烧录工具将固件烧写到 LZ3863-星闪开发板。

4.5、修改网络参数(可选)

烧录前,若实际 WiFi 热点与默认值不同,请编辑wifi_tcp_server_example.c中的宏定义:

#defineWIFI_SSID"lzdz"// 改为实际热点名称#defineWIFI_PASSWORD"88888888"// 改为实际热点密码#defineTCP_SERVER_PORT777// 改为实际监听端口

修改后需重新编译并烧录。


5、运行结果

5.1、硬件与网络准备

方式一:PC 移动热点 + PC 端 TCP 客户端(推荐)

  1. 在 PC 上开启移动热点,SSID 设为lzdz,密码设为88888888
  2. 开发板上电或复位,烧录本案例固件,通过 USB 连接 PC 打开串口助手(115200,8N1);
  3. 观察串口日志中打印的开发板 IP 地址(如STA IP 192.168.137.x);
  4. 在 PC 上使用 TCP 客户端连接该 IP 及端口777
# 方式 A:使用 netcat(Linux / macOS)nc192.168.137.x777# 方式 B:使用 Pythonpython3-c" import socket s = socket.socket() s.connect(('192.168.137.x',777))print('Connected to server') data = s.recv(1024) print(f'Received: {data.decode()}') s.send(b'Hello from TCP client!') s.close() "

192.168.137.x替换为串口日志中实际打印的开发板 IP。

方式二:使用 c2_wifi_tcp_client 案例联调

  1. 准备可连接的 WiFi 路由器或手机热点(SSID/密码与代码一致);
  2. 本开发板烧录c3_wifi_tcp_server固件作为 TCP 服务端;
  3. 另一块开发板烧录c2_wifi_tcp_client固件作为 TCP 客户端;
  4. 查看服务端串口日志中的 IP 地址,将其填入客户端案例的TCP_SERVER_IP宏定义后重新编译烧录客户端固件。

建议:先确认开发板 WiFi 连接成功并打印 IP 地址,再启动 TCP 客户端连接,以提高首次联调成功率。

5.2、串口配置

参数
波特率115200
数据位8
停止位1
校验位
流控

5.3、预期串口输出

烧录固件并复位后,串口助手可观察到完整的 WiFi 连接与 TCP 服务过程:

Starting Wi-Fi connection to SSID: lzdz... Start Scan ! [WIFI_STA_SAMPLE] Scan done!. STA try connect. [WIFI_STA_SAMPLE] Connect succ!. STA DHCP start. STA DHCP bound success. STA IP 192.168.137.x Connect success. Wi-Fi connected successfully. Bind to port 777 success! Listen with 1 backlog success! Accepted connection, connfd=3 Client info: IP=192.168.137.1, Port=xxxxx Sent data{wifi_tcp_test_date} 18 bytes to client! Received data{Hello from TCP client!} from client!

其中:

  • Start Scan !/Scan done!表示 WiFi 热点扫描完成;
  • Connect succ!/STA IP 192.168.137.x表示 WiFi 关联成功并获取 IP;
  • Wi-Fi connected successfully.表示应用层确认 WiFi 就绪;
  • Bind to port 777 success!表示端口绑定成功;
  • Listen with 1 backlog success!表示 TCP 服务已进入监听状态;
  • Accepted connection表示客户端连接建立(三次握手完成);
  • Sent data{wifi_tcp_test_date}表示初始数据发送成功;
  • Received data{...} from client!表示收到客户端发送的数据。

5.4、PC 端 TCP 客户端预期现象

若使用 netcat 或 Python 脚本作为客户端,PC 端可观察到:

Connected to server Received: wifi_tcp_test_date

表示开发板 TCP 服务端已成功接受连接并发送初始数据。

5.5、结果分析

现象说明
输出Wi-Fi connected successfully.WiFi 连接与 DHCP 获取 IP 成功
输出Bind to port 777 success!TCP 端口绑定成功
输出Listen with 1 backlog success!TCP 服务进入监听状态
输出Accepted connection客户端连接建立成功
输出Sent data{wifi_tcp_test_date}初始数据发送成功
输出Received data{...} from client!客户端数据接收成功
输出Failed to connect to AP.WiFi 连接失败,检查 SSID/密码
输出Bind to port 777 failed!端口被占用或权限不足
输出Accept connection failed!接受连接失败,检查网络状态
输出Recv data failed or connection closed客户端主动关闭连接或网络中断

5.6、常见问题排查

问题可能原因解决方法
反复Can not find AP热点未开启或 SSID/密码不匹配确认热点已开启,宏定义与实际一致
WiFi 成功但客户端无法连接使用了错误的 IP 地址以串口打印的STA IP为准,勿使用网关 IP
客户端Connection refused服务端尚未进入 listen 状态等待Listen with 1 backlog success!后再连接
Bind to port 777 failed!端口已被其他程序占用更换TCP_SERVER_PORT或重启开发板
PC 端连接超时防火墙拦截或不在同一网段确认 PC 与开发板连接同一热点,关闭防火墙
编译报错找不到组件BUILD.gn 或 config.py 未修改逐步核对 4.2、4.3 节的配置项
仅处理一个客户端代码设计为单连接模式正常现象,连接断开后需重启开发板再次 accept

6、实验扩展

完成基本实验后,可尝试以下扩展练习:

  1. 修改通信内容:更改send_data字符串,观察客户端接收到的数据变化;
  2. 双向通信:在recv()循环中增加send()回发逻辑,实现简单的请求-响应交互;
  3. 配合 TCP 客户端案例:使用c2_wifi_tcp_client案例,实现两块开发板之间的 TCP 通信;
  4. 多客户端支持:使用select()或循环accept()支持多个客户端同时连接;
  5. 断线重连:客户端断开后重新进入accept()等待新连接,实现服务端持续运行;
  6. 设置 SO_REUSEADDR:在bind()前设置地址复用选项,避免端口占用问题;
  7. 改用 UDP 通信:参考后续 UDP 案例,对比 TCP 服务端与 UDP 在可靠性、效率上的差异。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询