历史上的今天
今天是:2025年07月23日(星期三)
2019年07月23日 | STM32移植lwip之建立tcp客户端
2019-07-23 来源:eefocus
本篇目标:在之前能ping通pc机的工程基础上搭建tcp客户端,并可以主动发数据给pc机,同时也能与pc机收发数据,并在网络调试工具上显示
材料准备:
基础工程:修改后能ping通pc机的工程(STM32官方移植lwip修改代码)
调试工具:用来调试tcp连接下的数据接收(网络调试助手)
搭建工程:最终搭建好tcp客户端数据接收的工程(tcp客户端建立工程)
搭建TCP客户端
搭建TCP客户端的过程与上一章TCP服务器也相似,所以尽量把重点的地方加粗显示来区别
在搭建TCP客户端之前可以先理一下概念,客户端与服务器的区别:
客户端:主动建立tcp去连接目标IP
服务器:拥有静态IP,能让其他设备被动连接
因此用STM32搭建的TCP客户端主动去连接PC机创建的虚拟服务器,并完成收发数据的动作,接下来创建新的c文件,为tcp_client.c,编写三个函数:
tcp服务器初始化函数 Tcp_Client_Init() :
void Tcp_Client_Init(void)
{
struct tcp_pcb *tcp_client_pcb;
struct ip_addr ipaddr;
/* 将目标服务器的IP写入一个结构体 */
IP4_ADDR(&ipaddr, 192, 168, 0, 1);
/* 为tcp客户端分配一个tcp_pcb结构体 */
tcp_client_pcb = tcp_new();
/* 绑定本地端号和IP地址 */
tcp_bind(tcp_client_pcb, IP_ADDR_ANY, 80);
if (tcp_client_pcb != NULL)
{
/* 与目标服务器进行连接,参数包括了目标端口和目标IP */
tcp_connect(tcp_client_pcb, &ipaddr, 80, tcp_client_connected);
}
}
小结:上面函数主要就是为搭建tcp客户端做准备,将目标IP写入结构体,以后创建与目标服务器的连接,并设置了连接的回调函数;
连接回调函数 tcp_client_connected() :
static err_t tcp_client_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
/* 确认监听与连接 */
tcp_arg(pcb, mem_calloc(sizeof(struct name), 1));
/* 发送一个建立连接的问候字符串*/
tcp_write(pcb, "hello n", strlen("hello n"), 0);
/* 配置接收回调函数 */
tcp_recv(pcb, tcp_client_recv);
return ERR_OK;
}
小结:同样,这个函数最后通过最后一个函数的调用,指向接收处理数据的回调函数;
接收数据处理函数 tcp_client_recv() :
static err_t tcp_client_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, tcp_send_pbuf->payload, tcp_send_pbuf->len, 1);
/* 换行 */
tcp_write(pcb, "rn", strlen("rn"), 1);
pbuf_free(tcp_recv_pbuf);
}
else if (err == ERR_OK)
{
/* 释放内存 */
mem_free(name);
return tcp_close(pcb);
}
return ERR_OK;
}
小结:此函数将接收到的数据拷贝一份,然后再发送出去,实现简单的收发工程测试;
ps:tcp_client.c 还有头文件的包含,函数的定义;另外再编写一个tcp_client.h文件,包含宏定义,结构体定义,函数定义;在下面贴出这两个文件的源码;
接下来,只要在main函数添加初始化函数Tcp_Client_Init()就可以了,添加在while循环和lwip_init()之间就可以了,还不要忘了 #include “tcp_client.h”
文件源码
tcp_client.c
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "tcp_client.h"
#include #include #include /* ********************************************************************************************************* * LOCAL TABLES ********************************************************************************************************* */ static err_t tcp_client_connected(void *arg, struct tcp_pcb *pcb, err_t err); static err_t tcp_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *tcp_recv_pbuf, err_t err); /* ********************************************************************************************************* * LOCAL FUNCTION PROTOTYPES ********************************************************************************************************* */ /*** * 函数名称 : Tcp_Client_Init(); * * 函数描述 : TCP服务器初始化; * * 传递值 : 无; * * 返回值 : 无; * **/ void Tcp_Client_Init(void) { struct tcp_pcb *tcp_client_pcb; struct ip_addr ipaddr; /* 将目标服务器的IP写入一个结构体,为pc机本地连接IP地址 */ IP4_ADDR(&ipaddr, 192, 168, 0, 1); /* 为tcp客户端分配一个tcp_pcb结构体 */ tcp_client_pcb = tcp_new(); /* 绑定本地端号和IP地址 */ tcp_bind(tcp_client_pcb, IP_ADDR_ANY, 80); if (tcp_client_pcb != NULL) { /* 与目标服务器进行连接,参数包括了目标端口和目标IP */ tcp_connect(tcp_client_pcb, &ipaddr, 80, tcp_client_connected); } } /*** * 函数名称 : tcp_client_connected(); * * 函数描述 : lwip数据接收回调函数,包含对tcp连接的确认,接收回调函数的配置; * * 传递值 : *arg, *pcb, err ; * * 返回值 : ERR_OK 无错误; * **/ static err_t tcp_client_connected(void *arg, struct tcp_pcb *pcb, err_t err) { /* 确认监听与连接 */ tcp_arg(pcb, mem_calloc(sizeof(struct name), 1)); /* 发送一个建立连接的问候字符串*/ tcp_write(pcb, "hello n", strlen("hello n"), 0); /* 配置接收回调函数 */ tcp_recv(pcb, tcp_client_recv); return ERR_OK; } /*** * 函数名称 : tcp_client_recv(); * * 函数描述 : 接受到数据后,将数据拷贝转发出去; * * 传递值 : *arg, *pcb, *tcp_recv_pbuf, err; * * 返回值 : ERR_ARG 非法逻辑,ERR_OK无错误; * **/ static err_t tcp_client_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, tcp_send_pbuf->payload, tcp_send_pbuf->len, 1); /* 换行 */ tcp_write(pcb, "rn", strlen("rn"), 1); pbuf_free(tcp_recv_pbuf); } else if (err == ERR_OK) { /* 释放内存 */ mem_free(name); return tcp_close(pcb); } return ERR_OK; } tcp_client.h #ifndef TCP_CLIENT_H #define TCP_CLIENT_H /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ /* ********************************************************************************************************* * CONSTANTS ********************************************************************************************************* */ /* ********************************************************************************************************* * PERIPH DEFINES
史海拾趣
|
各位高手,我现在在写一个DMA的驱动,需要在一个接口中建立消息队列,在内存中开辟缓存的时候 请问该怎样实现?我看到有人说过在驱动中要避免使用malloc,因为sysHwInit()时内存未初始化, 会造成系统崩溃。我的函数类似下面这样: fun1(void *d ...… 查看全部问答> |
|
公司是致力于基于计算机的高端虚拟仪器设计与开发的研发类企业。欢迎有一定经验积累者问询和加盟。1、硬件工程师:1)本科及以上学历,测控、信号处理、仪器仪表、通信、电子信息等相关专业2)熟悉高速数字电路设计;数模混合电路设计,熟悉芯片和 ...… 查看全部问答> |
|
我遇到的问题是这样的:用zigbee节点采集两线制氨气变送器的数据无线发送给网关,zigbee节点采用的是飞思卡尔的芯片,氨气变送器输出时4-20ma的电流,zigbee节点采集的也是4-20ma电流,我测过氨气变送器输出时4-20ma稳定的电流值,接上节点后用万用 ...… 查看全部问答> |
|
昨天听世强组织的一场理光电源技术研讨会,对俺们这类菜鸟学到了不少知识,不过很多技术概念比较迷糊,听起来有些内容比较费劲。本来想会后向世强的FAE求教,不过貌似大家对理光的电源产品很感兴趣,把理光和世强的人围着问个不停,俺们菜鸟也智能 ...… 查看全部问答> |
|
焊盘的regular pad thermal relief和anti pad在某一层能同时存在吗 通孔类的via在内层时,它的regular pad thermal relief和anti pad同时存在的吗,还是三者是三种特性,在某一层只能选择其一作为和内层连接或者隔离?? … 查看全部问答> |
|
本帖最后由 ljj3166 于 2015-9-20 13:49 编辑 在活动DIY之前,一直很天真地以为TP4056这块充电IC能够直接给手机或者座充进行充电 随着活动的深入,发现它输出钳位至4.2v,基本上无法给手机直充 仔细想想,其实手机内部电路板上应该就有充电管IC ...… 查看全部问答> |
|
本帖最后由 airtight 于 2015-12-3 08:56 编辑 各位有项目经理吗?都是从技术人员做起的吗? 电子产品项目交流群,QQ群:203918642,欢迎入群!与业内同行一起交流! … 查看全部问答> |




