STM32移植lwip之建立tcp服务器
来源:互联网 发布:缩小手机屏幕的软件 编辑:程序博客网 时间:2024/05/20 12:22
本篇目标:在之前能ping通pc机的工程基础上搭建tcp连接,并可以收发数据,在网络调试工具上显示
材料准备:
- 基础工程:修改后能ping通pc机的工程(STM32官方移植lwip修改代码)
- 调试工具:用来调试tcp连接下的数据接收(网络调试助手)
- 搭建工程:最终搭建好tcp数据接收的工程(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 32struct 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机连接,打开网络调试助手:
- 顶部菜单选择网络调试
- 输入目标ip地址(我的stm32 ip地址:192.168.0.10)点击ping,ping通就ok
- 目标端口输入80
- 点击辅助-打开TCP,变成绿色,显示TCP连接成功
- 在发送区输入任意字符,点击TCP发送,接收区则显示你发送的字符
有图有真相:
总结:上面只是搭建了最简单的tcp服务器用来收发数据,理清tcp服务器建立过程再去看官网建立tcp服务器的程序,就会看的更加的明白,上面注释的也是函数表面的一些功能,没有很深入讲解,还需要多看看lwip的源码分析才能深刻了解几个建立tcp服务器的函数的机制作用,共勉~
0 0
- STM32移植lwip之建立tcp服务器
- STM32移植lwip之建立tcp客户端
- STM32移植lwip之建立web服务器
- STM32移植lwip之硬件连接
- STM32移植lwip之官方工程修改
- STM32移植lwip之官方源码解析
- LWIP 移植 stm32 注意事项
- stm32f103zet6+enc28j60上移植lwip,建立TCP客户端通信
- LWIP之TCP通信
- LWIP之TCP
- LwIP之TCP
- stm32上基于LwIP移植LibArtnet
- stm32移植lwip时遇到的问题。
- STM32移植LWIP验证DNS功能
- STM32 LWIP TCP以太网传输数据
- STM32 LWIP TCP 以太网调试注意问题
- lwip之http服务器
- lwIP(TCP/IP)协议栈移植
- 设置超时,timeout,socket
- 乐视的未来押在电视上,电视成则乐视成
- 对缓存的思考——提高命中率
- 数据结构
- uva1151 Buy or Build
- STM32移植lwip之建立tcp服务器
- 预编译——关于#和##
- session还是cookie
- Android多线程下载服务器资源
- BZOJ3630
- Android6.0蓝牙探索旅程
- n个骰子的点数之和
- 这几条UI原则可以让你的设计提高(中)
- 头尾式动画