【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); // 不应该到达这里
}
相关推荐
mounter6252 小时前
【硬核前沿】CXL 深度解析:重塑数据中心架构的“高速公路”,Linux 内核如何应对挑战?-- CXL 协议详解与 LSF/MM 最新动态
linux·服务器·网络·架构·kernel
ACP广源盛139246256734 小时前
破局 Type‑C 切换器痛点@ACP#GSV6155+LH3828/GSV2221+LH3828 黄金方案
c语言·开发语言·网络·人工智能·嵌入式硬件·计算机外设·电脑
嵌入式小企鹅6 小时前
蓝牙学习系列(八):BLE L2CAP 协议详解
网络·学习·蓝牙·ble·协议栈·l2cap
金戈鐡馬6 小时前
BetaFlight中的定时器引脚绑定详解
stm32·单片机·嵌入式硬件·无人机
广州灵眸科技有限公司7 小时前
为RK3588注入澎湃算力:RK1820 AI加速卡完整适配与评测指南
linux·网络·人工智能·物联网·算法
byoass7 小时前
csdn_upload_005
网络·安全·云计算
Wave8457 小时前
FreeRTOS软件定时器详解
stm32·单片机·freertos
IT WorryFree7 小时前
飞塔防火墙与第三方设备进行IPSEC故障诊断期间,用户可能会观察到以下错误:
linux·服务器·网络
不是书本的小明9 小时前
K8S应用优化方向
网络·容器·kubernetes
~plus~10 小时前
.NET 8 C# 委托与事件实战教程
网络·c#·.net·.net 8·委托与事件·c#进阶