【STM32】 LWIP -TCP 客户端收发数据

TCP 客户端收发数据,使用 FreeRTOS(CMSIS-RTOS V2),并兼容嵌入式环境(如 STM32 + LWIP)。

🔧 1. 头文件:tcp_client.h

c 复制代码
#ifndef TCP_CLIENT_H
#define TCP_CLIENT_H

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

#define TCP_SERVER_IP     "192.168.1.100"
#define TCP_SERVER_PORT   8080

extern int g_client_sock;
extern bool g_socket_connected;
extern char tcpClientRxBuffer[512];

void startTcpClient(void *argument);
void tcpSendData(const char *data, size_t len);

#endif

📂 2. 源文件:tcp_client.c

c 复制代码
#include "tcp_client.h"
#include "cmsis_os2.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

int g_client_sock = -1;
bool g_socket_connected = false;
char tcpClientRxBuffer[512];

void startTcpClient(void *argument)
{
    struct sockaddr_in server_addr;

    while (1) {
        g_client_sock = socket(AF_INET, SOCK_STREAM, 0);
        if (g_client_sock < 0) {
            printf("Socket creation failed: %d (%s)\n", errno, strerror(errno));
            osDelay(2000);
            continue;
        }

        memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(TCP_SERVER_PORT);

        if (inet_pton(AF_INET, TCP_SERVER_IP, &server_addr.sin_addr) <= 0) {
            printf("Invalid server IP\n");
            close(g_client_sock);
            g_client_sock = -1;
            osDelay(2000);
            continue;
        }

        printf("Connecting to %s:%d...\n", TCP_SERVER_IP, TCP_SERVER_PORT);
        if (connect(g_client_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
            printf("Connect failed: %d (%s)\n", errno, strerror(errno));
            close(g_client_sock);
            g_client_sock = -1;
            osDelay(2000);
            continue;
        }

        g_socket_connected = true;
        printf("Connected to TCP server!\n");

        while (1) {
            int ret = recv(g_client_sock, tcpClientRxBuffer, sizeof(tcpClientRxBuffer) - 1, MSG_DONTWAIT);
            if (ret > 0) {
                tcpClientRxBuffer[ret] = '\0';
                printf("Received: %s\n", tcpClientRxBuffer);
            } else if (ret == 0) {
                printf("Server closed connection\n");
                break;
            } else {
                if (errno != EAGAIN && errno != EWOULDBLOCK) {
                    printf("Recv error: %d (%s)\n", errno, strerror(errno));
                    break;
                }
            }

            osDelay(2);
        }

        close(g_client_sock);
        g_client_sock = -1;
        g_socket_connected = false;
        printf("Disconnected, retrying...\n");
        osDelay(3000);
    }
}

void tcpSendData(const char *data, size_t len)
{
    static uint8_t notConnectCounter = 0;

    if (g_socket_connected) {
        if (g_client_sock < 0) {
            notConnectCounter++;
            osDelay(50);
            if (notConnectCounter > 100) {
                g_socket_connected = false;
                notConnectCounter = 0;
            }
            return;
        }

        int sent = send(g_client_sock, data, len, 0);
        if (sent < 0) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                printf("Send buffer full, retrying...\n");
            } else {
                printf("Send failed: %d (%s)\n", errno, strerror(errno));
                close(g_client_sock);
                g_client_sock = -1;
                g_socket_connected = false;
            }
        }

    } else {
        notConnectCounter++;
        if (notConnectCounter > 100) {
            notConnectCounter = 0;
            printf("Socket not connected\n");
        }
        osDelay(50);
    }
}

⚙️ 3. FreeRTOS 任务创建:main.c 示例

c 复制代码
#include "cmsis_os2.h"
#include "tcp_client.h"

void app_main(void *argument) {
    while (1) {
        if (g_socket_connected) {
            tcpSendData("Hello Server!\n", strlen("Hello Server!\n"));
        }
        osDelay(1000);
    }
}

int main(void)
{
    // 硬件和网络初始化...

    osKernelInitialize();
    osThreadNew(startTcpClient, NULL, NULL);
    osThreadNew(app_main, NULL, NULL);
    osKernelStart();

    while (1); // 不应该到达这里
}
相关推荐
LCG元38 分钟前
STM32项目实战:基于STM32F103的智能农业监控系统
stm32·单片机·嵌入式硬件
ACP广源盛1392462567340 分钟前
IX8024与科学大模型的碰撞@ACP#筑牢科研 AI 算力高速枢纽分享
运维·服务器·网络·数据库·人工智能·嵌入式硬件·电脑
Empty-Filled1 小时前
AI生成测试用例功能怎么测:一个完整实战案例
网络·人工智能·测试用例
码云数智-大飞2 小时前
本地部署大模型:隐私安全与多元优势一站式解读
运维·网络·人工智能
jinanwuhuaguo2 小时前
(第二十九篇)OpenClaw 实时与具身的跃迁——从异步孤岛到数字世界的“原住民”
前端·网络·人工智能·重构·openclaw
Truffle7电子3 小时前
STM32CubeIDE/Programmer/Touch GFX 应用
stm32·单片机·嵌入式硬件
等风来不如迎风去3 小时前
【win11】最佳性能:fix 没有壁纸,一直黑屏
网络·人工智能
Harvy_没救了3 小时前
【网络部署】 Win11 + VMware CentOS8 + Nginx 文件共享服务 Wiki
运维·网络·nginx
汤愈韬4 小时前
NAT Server 与目的Nat
网络·网络协议·网络安全·security
richxu202510014 小时前
嵌入式学习之路->stm32篇->(14)通用定时器(上)
stm32·单片机·嵌入式硬件·学习