【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); // 不应该到达这里
}
相关推荐
无足鸟ICT26 分钟前
【RHCA+】iptraf-ng(网络监控分析)
linux·网络
Zw-awa39 分钟前
屏幕不止一种:OLED、LCD1602字符屏、TFT/IPS图形屏和串口屏怎么用,这与TTY和PTY又有什么关系
stm32
坤坤子吖2 小时前
Linux网络编程:TCP服务器的多进程与多线程实现
linux·服务器·开发语言·网络·c++·笔记·学习
无敌贵点大王3 小时前
从寄存器层面重学STM32(7)——定时器
stm32·单片机·嵌入式硬件
xiaoye-duck4 小时前
《C++ 项目:手写大模型接入 SDK》LLMManager架构设计与实现
开发语言·网络·c++·语言模型
andxe5 小时前
工业级 PoE 交换机选型指南:破解边缘部署四大核心难题
运维·网络·安全·光通信·交换机
say_fall7 小时前
【Linux网络编程】计算机网络基础:局域网与广域网、OSI七层模型与TCP/IP五层模型、封装解包与MAC/IP地址、端口号与socket编程接口
linux·网络·tcp/ip·计算机网络·信息与通信
Joy T7 小时前
Gzip 压缩原理与实践:HTTP 响应压缩、性能收益与工程配置
网络·网络协议·http
叼烟扛炮7 小时前
Linux 学习笔记(五十四):内网穿透实战——用 frp 让外网访问你的私人电脑
linux·服务器·网络·笔记·学习
流浪0019 小时前
计算机网络篇22:网络层——公网的三级地址划分与逐跳转发,从私网出口替换到 IP 分片组装
tcp/ip·计算机网络·路由器·公网搭建·报文分篇