STM32移植lwip之建立tcp服务器

2023-10-31

本篇目标:在之前能ping通pc机的工程基础上搭建tcp连接,并可以收发数据,在网络调试工具上显示

材料准备:


搭建TCP服务器

之前已经能够让pc机ping通stm32了,说明PHY网卡已经正确工作了,现在可以使用lwip的函数来建立tcp服务器了;
现在创建一个新的c文件,取名为 tcp_server.c ,接下来要写三个函数:

  • tcp服务器初始化函数 Tcp_Server_Init():
void Tcp_Server_Init(void)
{
        struct tcp_pcb *tcp_server_pcb;

        /* 为tcp服务器分配一个tcp_pcb结构体    */
        tcp_server_pcb = tcp_new();

        /* 绑定本地端号和IP地址 */
        tcp_bind(tcp_server_pcb, IP_ADDR_ANY, 80);

        /* 监听之前创建的结构体tcp_server_pcb */
        tcp_server_pcb = tcp_listen(tcp_server_pcb);

        /* 初始化结构体接收回调函数 */
        tcp_accept(tcp_server_pcb, tcp_server_accept);
}

小结:上面函数主要就是为搭建tcp连接做准备,包括申请网络结构体、设置80端口号、监听数据、设置接收数据回调函数;

  • 接收数据回调函数 tcp_server_accept() :
static err_t tcp_server_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
        /* 确认监听与连接 */
        tcp_arg(pcb, mem_calloc(sizeof(struct name), 1));

        /* 发送一个建立连接的字符串 */
        tcp_write(pcb, "hello my dream \n\r",strlen("hello my dream \n\r  "), 1);

        /* 配置接收回调函数 */
        tcp_recv(pcb, tcp_server_recv);

        return ERR_OK;
}

小结:这个函数最重要的就是最后一个函数,它指向了处理接收数据的函数;

  • 接收数据处理函数 tcp_server_recv() :
static err_t tcp_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *tcp_recv_pbuf, err_t err)
{
        struct pbuf *tcp_send_pbuf;
        struct name *name = (struct name *)arg;

        if (tcp_recv_pbuf != NULL)
        {
                /* 扩大收发数据的窗口 */
                tcp_recved(pcb, tcp_recv_pbuf->tot_len);

                if (!name)
                {
                        pbuf_free(tcp_recv_pbuf);
                        return ERR_ARG;
                }

                /* 将接收的数据拷贝给发送结构体 */
                tcp_send_pbuf = tcp_recv_pbuf;

                /* 换行 */
                tcp_write(pcb, "\r\n", strlen("\r\n"), 1);
                /* 将接收到的数据再转发出去 */
                tcp_write(pcb, tcp_send_pbuf->payload, tcp_send_pbuf->len, 1);

                pbuf_free(tcp_recv_pbuf);
        }
        else if (err == ERR_OK)
        {
                /* 释放内存 */
                mem_free(name);
                return tcp_close(pcb);
        }

        return ERR_OK;
}

小结:此函数将接收到的数据拷贝一份,然后再发送出去,实现简单的收发工程测试;

ps:tcp_server.c 还有头文件的包含,函数的定义;另外再编写一个tcp_server.h文件,包含宏定义,结构体定义,函数定义;在下面贴出这两个文件的源码;

接下来,只要在main函数添加初始化函数Tcp_Server_Init()就可以了,添加在while循环和lwip_init()之间就可以了,还不要忘了 #include “tcp_server.h”

文件源码

  • tcp_server.c
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "tcp_server.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/*
*********************************************************************************************************
*                                            LOCAL TABLES
*********************************************************************************************************
*/
static err_t tcp_server_accept(void *arg, struct tcp_pcb *pcb, err_t err);
static err_t tcp_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);

/*
*********************************************************************************************************
*                                      LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/

/***
 * 函数名称 : Tcp_Server_Init();
 *
 * 函数描述 : TCP服务器初始化;
 *
 * 传递值   : 无;
 *
 * 返回值   : 无;
 *
 **/
void Tcp_Server_Init(void)
{
        struct tcp_pcb *tcp_server_pcb;

        /* 为tcp服务器分配一个tcp_pcb结构体    */
        tcp_server_pcb = tcp_new();

        /* 绑定本地端号和IP地址 */
        tcp_bind(tcp_server_pcb, IP_ADDR_ANY, 80);

        /* 监听之前创建的结构体tcp_server_pcb */
        tcp_server_pcb = tcp_listen(tcp_server_pcb);

        /* 初始化结构体接收回调函数 */
        tcp_accept(tcp_server_pcb, tcp_server_accept);
}

/***
 * 函数名称 : tcp_server_accept();
 *
 * 函数描述 : lwip数据接收回调函数,包含对tcp连接的确认,接收回调函数的配置;
 *
 * 传递值   : *arg, *pcb, err ;
 *
 * 返回值   : ERR_OK 无错误;
 *
 **/
static err_t tcp_server_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
        /* 确认监听与连接 */
      tcp_arg(pcb, mem_calloc(sizeof(struct name), 1));

        /* 发送一个建立连接的字符串 */
        tcp_write(pcb, "hello my dream \n\r",strlen("hello my dream \n\r  "), 1);

        /* 配置接收回调函数 */
        tcp_recv(pcb, tcp_server_recv);

        return ERR_OK;
}

/***
 * 函数名称 : tcp_server_recv();
 *
 * 函数描述 : 接受到数据后,将数据拷贝转发出去;
 *
 * 传递值   : *arg, *pcb, *tcp_recv_pbuf, err;
 *
 * 返回值   : ERR_ARG 非法逻辑,ERR_OK无错误;
 *
 **/
static err_t tcp_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *tcp_recv_pbuf, err_t err)
{
        struct pbuf *tcp_send_pbuf;
        struct name *name = (struct name *)arg;

        if (tcp_recv_pbuf != NULL)
        {
                /* 扩大收发数据的窗口 */
                tcp_recved(pcb, tcp_recv_pbuf->tot_len);

                if (!name)
                {
                        pbuf_free(tcp_recv_pbuf);
                        return ERR_ARG;
                }

                /* 将接收的数据拷贝给发送结构体 */
                tcp_send_pbuf = tcp_recv_pbuf;

                /* 换行 */
                tcp_write(pcb, "\r\n", strlen("\r\n"), 1);
                /* 将接收到的数据再转发出去 */
                tcp_write(pcb, tcp_send_pbuf->payload, tcp_send_pbuf->len, 1);

                pbuf_free(tcp_recv_pbuf);
        }
        else if (err == ERR_OK)
        {
                /* 释放内存 */
                mem_free(name);
                return tcp_close(pcb);
        }

        return ERR_OK;
}
  • tcp_server.h
#ifndef TCP_SERVER_H
#define TCP_SERVER_H

/*
*********************************************************************************************************
*                                              INCLUDE FILES
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                               CONSTANTS
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                             PERIPH DEFINES
*********************************************************************************************************
*/
#define     MAX_NAME_SIZE       32

struct name
{
        int     length;
        char    bytes[MAX_NAME_SIZE];
};

/*
*********************************************************************************************************
*                                               DATA TYPES
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                            GLOBAL VARIABLES
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                                 MACRO'S
*********************************************************************************************************
*/



/*
*********************************************************************************************************
*                                           FUNCTION PROTOTYPES
*********************************************************************************************************
*/

void Tcp_Server_Init(void);

/*
********************************************************************************************************
*                                             MODULE END
*********************************************************************************************************
*/

#endif /* TCP_SERVER_H */

tcp服务器收发测试

将工程编译后,烧进stm32,将网线与pc机连接,打开网络调试助手:

  1. 顶部菜单选择网络调试
  2. 输入目标ip地址(我的stm32 ip地址:192.168.0.10)点击ping,ping通就ok
  3. 目标端口输入80
  4. 点击辅助-打开TCP,变成绿色,显示TCP连接成功
  5. 在发送区输入任意字符,点击TCP发送,接收区则显示你发送的字符

有图有真相:

tcp服务器收发测试


总结:上面只是搭建了最简单的tcp服务器用来收发数据,理清tcp服务器建立过程再去看官网建立tcp服务器的程序,就会看的更加的明白,上面注释的也是函数表面的一些功能,没有很深入讲解,还需要多看看lwip的源码分析才能深刻了解几个建立tcp服务器的函数的机制作用,共勉~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32移植lwip之建立tcp服务器 的相关文章

  • 处理器指令周期执行时间

    我的猜测是 no operation 内在 ARM 指令应花费 1 168 MHz 来执行 前提是每个NOP在一个时钟周期内执行 我想通过文档验证这一点 有关处理器指令周期执行时间的信息是否有标准位置 我试图确定 STM32f407IGh6
  • 初始化 ST-Link 设备时出错 - 无法连接到设备

    我目前正在使用 ST Link 调试器对我的 STM32F3 Discovery 板进行编程 我使用的IDE是Atollic TrueStudio 5 5 2 现在我面临一个非常奇怪的问题 那就是我不断收到消息 初始化 ST Link 设备
  • c项目makefile多重定义错误

    这个问题是一个对应于创建的repexthis问题 在我的嵌入式 C 项目中 我有两个独立的板 我想为每个板创建两个 c 文件 master c 和 Slave c 其中包含自己的特定main 功能 我使用 stm32cumbemx 生成带有
  • 134-基于stm32单片机矿井瓦斯天然气浓度温湿度检测自动通风系统Proteus仿真+源程序...

    资料编号 134 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 ds1302时钟 DHT11温湿度 电机 蜂鸣器 制作一个基于stm32单片机矿井瓦斯天然气浓度温湿度检测自动通风系统Proteus仿真 2 通过DH
  • HAL库STM32常用外设教程(二)—— GPIO输入\输出

    HAL库STM32常用外设教程 二 GPIO输入 输出 文章目录 HAL库STM32常用外设教程 二 GPIO输入 输出 前言 一 GPIO功能概述 二 GPIO的HAl库驱动 三 GPIO使用示例 1 示例功能 四 代码讲解 五 总结
  • STM32F4 通过软复位跳转到引导加载程序,无需 BOOT0 和 BOOT1 引脚

    我问这个问题是因为可以在这里找到类似问题的答案 通过应用程序跳转到 STM32 中的引导加载程序 即从用户闪存在引导模式下使用引导 0 和引导 1 引脚 用户 JF002 JF002回答 当我想跳转到引导加载程序时 我在其中一个备份寄存器中
  • 物联网网关

    物联网网关是 连接物联网设备和互联网的重要桥梁 它负责将物联网设备采集到的数据进行处理 存储和转发 使其能够与云端或其它设备进行通信 物联网网关的作用是实现物联网设备与云端的无缝连接和数据交互 物联网网关功能 数据采集 物联网网关可以从物联
  • STM32 GPIO工作原理详解

    STM32 GPIO介绍 1 STM32引脚说明 GPIO是通用输入 输出端口的简称 是STM32可控制的引脚 GPIO的引脚与外部硬件设备连接 可实现与外部通讯 控制外部硬件或者采集外部硬件数据的功能 以STM32F103ZET6芯片为例
  • [MM32硬件]搭建灵动微MM32G0001A6T的简易开发环境

    作为学习单片机的经典 自然是通过GPIO点亮LED 或者是响应按钮的外部中断例程 这我们看看SOP8封装的芯片MM32G0001A6T得引脚 除了VDD和GND固定外 我们可以使用PA14 PA1 PA13 PA15 PA2 PA3这六个G
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • VS Code 有没有办法导入 Makefile 项目?

    正如标题所说 我可以从现有的 Makefile 自动填充 c cpp properties json 吗 Edit 对于其他尝试导入 makefile 的人 我找到了一组脚本 它们完全可以实现我想要实现的目标 即通过 VS Code 管理
  • STM32的HAL中实现单按、长按和双按功能

    我正在尝试实现单击 双击和长按功能来执行不同的功能 到目前为止 我已经理解了单击和长按的逻辑 但我不知道如何检测双击 至于代码 我使用计数器实现了单击和长按 但代码仅停留在第一个 if 条件上 bool single press false
  • 无法使用 OpenOCD 找到脚本文件

    我正在尝试按照本教程将 OpenOCD 与我的 ST 发现板一起使用 https japaric github io discovery README html https japaric github io discovery READM
  • CMSIS & STM32,如何开始? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 STM32 上使用 CMSIS 启动项目 网上一搜 没找到具体的教程 有些使用 SPL 开始项
  • systick定时器

    systick定时器 文章目录 前言 一 前期疑惑 二 解答 1 关于systick是阻塞的吗 2 非阻塞 三 软件编写 总结 前言 这边记录systick相关知识点 一 前期疑惑 在学习systick志气啊 其实对于systick还是一脸
  • Cortex-M3与M4权威指南

    处理器类型 所有的ARM Cortex M 处理器是32位的精简指令集处理器 它们有 32位寄存器 32位内部数据路径 32位总线接口 除了32位数据 Cortex M处理器也可以有效地处理器8位和16位数据以及支持许多涉及64位数据的操作
  • 核心耦合内存在 STM32F4xx 上可执行吗?

    尝试从 STM32F429s CCM 运行代码 但每当我命中 CCM 中的第一条指令时 我总是会遇到硬故障 并且 IBUSERR 标志被设置 该指令有效且一致 STM32F4xx 是否可能不允许从 CCM 执行 数据访问效果良好 alios
  • 在 Contiki 程序中使用 malloc

    考虑以下 Contiki 程序 include
  • HAL_Delay() 陷入无限循环

    我被 HAL Delay 函数困住了 当我调用此函数 HAL Delay 时 控制陷入无限循环 在寻找问题的过程中 我发现了这个 http www openstm32 org forumthread2145 threadId2146 htt
  • 使用 STM32 USB 设备库将闪存作为大容量存储设备

    我的板上有这个闪存IC 它连接到我的STM32F04 ARM处理器 处理器的USB端口可供用户使用 我希望我的闪存在通过 USB 连接到 PC 时被检测为存储设备 作为第一步 我在程序中将 USB 类定义为 MSC 效果很好 因为当我将主板

随机推荐

  • mysql锁总结

    参考文章 MySQL 死锁查询 事务与锁详解2 MySQL死锁系列 常见加锁场景分析 死锁的成因 场景以及死锁的避免 查询锁sql 1 查看当前的事务 SELECT FROM INFORMATION SCHEMA INNODB TRX 2
  • 解决centos下sudo运行tshark,写入文件显示:Permission denied.

    在 w时 需要把文件名写全 相对路径无权限 则需要写成绝对路径 比如 sudo tshark w home xxxx mypcap pcap 下面的不行 sudo tshark w mypcap pcap Permission denied
  • 走线和交互式布线_画PCB时,一些非常好的布线技巧

    画PCB时 一些非常好的布线技巧 布线是PCB设计过程中技巧最细 限定最高的 即使布了十几年布线的工程师也往往觉得自己不会布线 因为看到了形形色色的问题 知道了这根线布了出去就会导致什么恶果 所以 就变的不知道怎么布了 但是高手还是有的 他
  • spring cloud 2021.0.1升级踩坑记录

    一 版本说明 升级前的版本 spring boot 2 2 2 RELEASE spring cloud Hoxton SR1 spring cloud alibaba 2 2 0 RELEASE 升级后版本 spring boot 2 6
  • linux测试代码段运行时间,如何精确测量一段代码的执行时间

    原标题 如何精确测量一段代码的执行时间 本文转载自西邮Linux兴趣小组 最近在工作中遇到了需要精确测量一段C代码执行时间的需求 这里有三种方案供大家选择 1 gettimeofday 2 2 rdtsc rdtscp 3 clock ge
  • 工程师的自我修养:全英文技术学习实践

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 引子 2016年9月 上海GOPS大会现场 Site Reliability Engineering 一书的作者之一 来自Google的Chris Jones在做分享 Ch
  • linux内核添加模块,linux中添加内核模块

    1 内核模块简介 Linux 内核的 整 体结构 非 常 庞 大 其 包 含 的 组 件也 非 常多 如 何使用 需 要 的 组 件 呢 方 法 一 把 所有的 组 件都 编译 进 内核 文 件 即 zImage 或bzImage 但 这样
  • 【MYSQL基础】SQL-DML(数据操作语言)

    文章目录 一 DML 介绍 二 DML 语法 2 1DML 添加 插入数据 2 2DML 修改 更新数据 2 3DML 删除数据 一 DML 介绍 DML Data Manipulation Language 数据操作语言 用来对数据库中表
  • 华夏大盘精选基金经理王亚伟:08年做不好会赔钱

    编者按 华夏基金投资决策委员会主席 华夏大盘精选基金经理王亚伟在华夏基金08年投资策略报告会上对明年资本市场的走势发表了自己的看法 王亚伟 尊敬的各位领导 各位来宾 下午好 刚才两位名嘴很精彩 现在基金行业总体来说是越来越娱乐化了 基金经理
  • 12. XPath解析入门

    目录 前言 模块安装 XPath涉及的基本概念 XPath基本语法 测试完整代码 XPath进阶用法 需求1 让xpath处理这个资源文件 需求2 找到标签位置 如html标签 需求3 找到无序列表 ul 中每一项 li 包裹的文本内容 需
  • 树莓派——配置Linux内核适合树莓派

    文章目录 将linux内核代码和编译工具tools上传到ubuntu 树莓派等芯片带操作系统的启动过程 不带操作系统的 带操作系统的 BootLoader的工作流程 树莓派Linux源码目录树分析 树莓派Linux源码配置 Linux源码特
  • 【数据结构】插入排序 & 希尔排序

    目录 插入排序 希尔排序 插入排序 时间复杂度 O N 2 空间复杂度 O 1 稳定性 稳定 void InsertSort int arr int size for int i 0 i lt size 1 i int end i int
  • easyexcel 第一次导入导出会报错com.alibaba.excel.exception.ExcelAnalysisException,所以自定义excel导入导出表格

    报错原因 由于easyexcel导入导出时如果存在null会报错 跟踪源码com alibaba excel analysis v07 XlsxSaxAnalyser parseXmlSource 查看xmlReader parse 发现这
  • vi 操作

    vi filename c vi 457 filename c 打开文件同时跳至457行 exc 由输入状态退出到控制命令状态 shirt zz 保存并退出 w 保存退出 q 不保存退出 457 跳至457行 set nu 在前面列出行号
  • 大数据教育平台数据仓库系统搭建 附安装包与脚本

    一 数仓项目需求及架构设计 数据仓库是为企业所有级别的决策制定过程 提供所有类型数据支持的战略集合 数据仓库是出于分析报告和决策支持目的而创建的 为需要业务智能的企业 提供指导业务流程改进 监控时间 成本 质量以及控制 1 项目需求分析 数
  • Xilinx软件开发: 用仿真器在XSCT下加载u-boot

    XSCT介绍 XSCT全称叫做Xilinx Software Command Line Tool 顾名思义是Xilinx提供的软件命令行工具 完整的使用说明可以参考ug1208 xsct reference guide 我们平常调试裸机程序
  • Gradle 5.0 更新介绍

    Gradle 5 0正式版出来有几天了 这个工具的发展速度还真是惊人 前些天我看到gradle 5 rc版的时候还在想正式版什么时候出 没想到rc版没过几天正式版就出来了 那么正好 就来介绍一下gradle 5 0正式版加入的一些新功能吧
  • json字段 react_react 解析json

    Copyright 2013 2017 David Caldwell Permission to use copy modify and or distribute this software for any purpose with or
  • Python的sort函数和sorted、lambda和cmp

    1 sort和sorted 我们需要对List进行排序 Python提供了两个方法 对给定的List L进行排序 方法1 用List的成员函数sort进行排序 方法2 用built in函数sorted进行排序 从2 4开始 iterabl
  • STM32移植lwip之建立tcp服务器

    本篇目标 在之前能ping通pc机的工程基础上搭建tcp连接 并可以收发数据 在网络调试工具上显示 材料准备 基础工程 修改后能ping通pc机的工程 STM32官方移植lwip修改代码 调试工具 用来调试tcp连接下的数据接收 网络调试助