OpenHarmony(鸿蒙)RK2206 实现稳定 TCP 客户端 Socket 通信(一发一收+自动重连)
前言
在物联网开发中,TCP 网络通信 是设备与服务器数据交互的核心功能。本文基于 OpenHarmony 轻量级系统 + Rockchip RK2206 开发板 ,实现一套稳定可靠的 TCP 客户端:包含 WiFi 自动等待连接、TCP 服务器连接、循环一发一收、异常断开自动重连,代码经过实测优化,可直接移植使用。
一、开发环境与硬件
- 开发板:RK2206 开发板(Lockzhiner 生态)
- 系统:OpenHarmony 轻量级系统
- 功能:WiFi 联网 + TCP 客户端通信
- 核心:单任务一发一收、断连自动重连、计数稳定不重复
二、核心知识点
- WiFi 状态检测:等待 WiFi 连接成功并获取 IP 后再进行网络操作
- LwIP 套接字编程:标准 socket/connect/send/recv 接口
- TCP 异常处理:发送/接收失败立即关闭套接字并标记重连
- 稳定计数机制:发送成功后才计数,避免重复发送/丢包计数错乱
- LiteOS 任务创建:OpenHarmony 轻量级系统任务启动方式
三、完整代码实现
代码结构清晰,包含 WiFi 等待、TCP 连接、一发一收、自动重连,直接复制即可编译运行。
c
/*
* Copyright (c) 2022 FuZhou Lockzhiner Electronic Co., Ltd. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* http://www.apache.org/licenses/LICENSE2.0
*/
#include "ohos_init.h"
#include "los_task.h"
#include "lz_hardware.h"
#include "config_network.h"
#include "lwip/sockets.h"
#include "lwip/netdb.h"
#include <stdio.h>
#include <string.h>
// ===================== 配置参数 =====================
#define SERVER_IP "192.168.111.61" // 服务器 IP
#define SERVER_PORT 20108 // 服务器端口
#define BUF_SIZE 256 // 收发缓冲区大小
// 全局套接字
static int g_tcp_fd = -1;
/************************************************************
函数名称:wait_wifi_connected
函数功能:阻塞等待 WiFi 连接成功并获取 IP
入口参数:无
返 回 值:0-成功
************************************************************/
int wait_wifi_connected(void)
{
WifiLinkedInfo info;
while (1)
{
// 获取 WiFi 连接状态
if (GetLinkedInfo(&info) == WIFI_SUCCESS &&
info.connState == WIFI_CONNECTED && info.ipAddress != 0)
{
printf("WiFi 已连接 IP: %s\n", inet_ntoa(info.ipAddress));
return 0;
}
// 每秒查询一次
LOS_Msleep(1000);
}
}
/************************************************************
函数名称:tcp_connect_server
函数功能:创建 socket 并连接 TCP 服务器
入口参数:无
返 回 值:0-成功,-1-失败
************************************************************/
int tcp_connect_server(void)
{
struct sockaddr_in server_addr;
// 安全关闭旧的 socket,防止文件描述符泄漏
if (g_tcp_fd >= 0)
{
close(g_tcp_fd);
g_tcp_fd = -1;
}
// 创建 TCP 套接字
g_tcp_fd = socket(AF_INET, SOCK_STREAM, 0);
if (g_tcp_fd < 0)
{
printf("socket 创建失败\n");
return -1;
}
// 配置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
// 发起连接
if (connect(g_tcp_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
close(g_tcp_fd);
g_tcp_fd = -1;
printf("TCP 连接失败\n");
return -1;
}
printf("TCP 连接成功!\n");
return 0;
}
/************************************************************
函数名称:tcp_single_task
函数功能:TCP 单发单收任务,自动重连
入口参数:无
返 回 值:无
************************************************************/
void tcp_single_task(void)
{
char send_buf[BUF_SIZE];
char recv_buf[BUF_SIZE];
static int cnt = 0; // 静态全局计数,仅发送成功后累加
// 第一步:等待 WiFi 联网
wait_wifi_connected();
while (1)
{
// 未连接则循环尝试重连
if (g_tcp_fd < 0)
{
tcp_connect_server();
LOS_Msleep(1000);
continue;
}
// ===================== 发送数据 =====================
snprintf(send_buf, BUF_SIZE, "RK2206 TCP Socket: %d\r\n", cnt);
int ret = send(g_tcp_fd, send_buf, strlen(send_buf), 0);
// 发送失败:关闭 socket,等待重连
if (ret <= 0)
{
printf("%d 发送失败,断开连接\n", cnt);
close(g_tcp_fd);
g_tcp_fd = -1;
LOS_Msleep(1000);
continue;
}
// 关键:发送成功后计数 +1
cnt++;
printf("[TCP 发送] %s", send_buf);
// ===================== 接收数据 =====================
ret = recv(g_tcp_fd, recv_buf, BUF_SIZE - 1, 0);
if (ret > 0)
{
recv_buf[ret] = '\0';
printf("[TCP 接收] %s\n", recv_buf);
}
else
{
// 接收失败:服务器断开或网络异常
printf("服务器断开连接\n");
close(g_tcp_fd);
g_tcp_fd = -1;
}
// 发送间隔 1 秒
LOS_Msleep(1000);
}
}
/************************************************************
函数名称:tcp_client_socket_example
函数功能:创建 TCP 任务
入口参数:无
返 回 值:无
************************************************************/
void tcp_client_socket_example(void)
{
unsigned int thread_id;
TSK_INIT_PARAM_S task = {0};
task.pfnTaskEntry = (TSK_ENTRY_FUNC)tcp_single_task;
task.uwStackSize = 10240; // 栈大小 10K
task.pcName = "tcp_single_task";
task.usTaskPrio = 24; // 任务优先级
LOS_TaskCreate(&thread_id, &task);
}
// 系统启动时自动初始化
APP_FEATURE_INIT(tcp_client_socket_example);
四、代码核心解析
1. WiFi 连接等待
设备上电后,必须等待 WiFi 连接成功并获取到 IP,才能进行 TCP 连接,避免网络未就绪导致连接失败。
c
int wait_wifi_connected(void)
{
WifiLinkedInfo info;
while (1)
{
if (GetLinkedInfo(&info) == WIFI_SUCCESS &&
info.connState == WIFI_CONNECTED && info.ipAddress != 0)
{
printf("WiFi 已连接 IP: %s\n", inet_ntoa(info.ipAddress));
return 0;
}
LOS_Msleep(1000);
}
}
2. TCP 服务器连接
- 安全关闭旧 socket,防止文件描述符泄漏
- 标准
socket + connect流程 - 连接失败自动标记
g_tcp_fd = -1,触发重连
3. 稳定一发一收(核心优化)
重点改进 :只有发送成功,计数器才 +1,彻底解决断连、重发导致的计数重复/错乱问题。
c
// 发送成功后才计数 +1,保证数据有序不重复
cnt++;
printf("[TCP 发送] %s", send_buf);
4. 异常自动重连
- send 返回 ≤0 → 发送失败 → 关闭 socket → 标记重连
- recv 返回 ≤0 → 服务器断开 → 关闭 socket → 标记重连
- 主循环检测
g_tcp_fd < 0自动重试连接
五、使用说明
- 修改代码中的 SERVER_IP 和 SERVER_PORT 为你的服务器地址
- 确保 RK2206 与服务器在同一局域网
- 编译固件并烧录到开发板
- 打开串口监视器,查看日志:
- WiFi 连接成功
- TCP 连接成功
- 每秒发送一条数据,接收服务器回复
- 断网/重启服务器后,设备自动重连
六、日志输出示例
log
WiFi 已连接 IP: 192.168.111.100
TCP 连接成功!
[TCP 发送] RK2206 TCP Socket: 0
[TCP 接收] 服务器回复:收到 0
[TCP 发送] RK2206 TCP Socket: 1
[TCP 接收] 服务器回复:收到 1
服务器断开连接
TCP 连接成功!
[TCP 发送] RK2206 TCP Socket: 2
[TCP 接收] 服务器回复:收到 2

七、总结
本文实现了 OpenHarmony + RK2206 平台下工业级稳定的 TCP 客户端,具备以下优点:
- 联网等待:WiFi 就绪才启动 TCP,避免无效连接
- 自动重连:网络异常、服务器重启后自动恢复
- 数据稳定:发送成功才计数,无重复、无丢包错乱
- 代码规范:文件描述符安全关闭、异常处理完善,适合产品级使用
这套代码可直接用于物联网网关、传感器、控制设备等 TCP 通信场景,快速对接云服务器/本地服务器。