30 OpenHarmony(鸿蒙)RK2206 实现稳定 TCP 客户端 Socket 通信(一发一收+自动重连)

OpenHarmony(鸿蒙)RK2206 实现稳定 TCP 客户端 Socket 通信(一发一收+自动重连)

前言

在物联网开发中,TCP 网络通信 是设备与服务器数据交互的核心功能。本文基于 OpenHarmony 轻量级系统 + Rockchip RK2206 开发板 ,实现一套稳定可靠的 TCP 客户端:包含 WiFi 自动等待连接、TCP 服务器连接、循环一发一收、异常断开自动重连,代码经过实测优化,可直接移植使用。

一、开发环境与硬件

  • 开发板:RK2206 开发板(Lockzhiner 生态)
  • 系统:OpenHarmony 轻量级系统
  • 功能:WiFi 联网 + TCP 客户端通信
  • 核心:单任务一发一收、断连自动重连、计数稳定不重复

二、核心知识点

  1. WiFi 状态检测:等待 WiFi 连接成功并获取 IP 后再进行网络操作
  2. LwIP 套接字编程:标准 socket/connect/send/recv 接口
  3. TCP 异常处理:发送/接收失败立即关闭套接字并标记重连
  4. 稳定计数机制:发送成功后才计数,避免重复发送/丢包计数错乱
  5. 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 自动重试连接

五、使用说明

  1. 修改代码中的 SERVER_IPSERVER_PORT 为你的服务器地址
  2. 确保 RK2206 与服务器在同一局域网
  3. 编译固件并烧录到开发板
  4. 打开串口监视器,查看日志:
    • 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 客户端,具备以下优点:

  1. 联网等待:WiFi 就绪才启动 TCP,避免无效连接
  2. 自动重连:网络异常、服务器重启后自动恢复
  3. 数据稳定:发送成功才计数,无重复、无丢包错乱
  4. 代码规范:文件描述符安全关闭、异常处理完善,适合产品级使用

这套代码可直接用于物联网网关、传感器、控制设备等 TCP 通信场景,快速对接云服务器/本地服务器。