CubeMX配置STM32实现httpd服务器CGI功能并使用网页控制STM32单片机(四)
CubeMX配置STM32实现httpd服务器CGI功能并使用网页控制STM32单片机
- 引言
- CubeMX配置HTTPD的CGI功能
- 实验过程
- 发现的问题
- 总结
引言
在前三篇文章中自己介绍了如何配置freeRTOS以及如何配置LWIP,并使用lwip实现一个httpd服务器,使浏览器可以访问。在本章中我们利用CGI功能,实现通过网页来控制单片机的一个LED灯的电平翻转。
自己写的另外五篇文章
从零开始Cubemx配置STM32搭载freeRTOS实现多路ADC(一)
从零开始Cubemx配置STM32搭载freeRTOS以及lwip实现tcp网络通信(二)
从零开始使用CubeMX配置STM32使用lwip实现httpd服务器以及使用vscode编辑阅读keil代码(三)
CubeMX配置STM32实现FatFS文件系统(五)
CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC
CubeMX配置HTTPD的CGI功能
在这里把CGI功能开启。
CGI的介绍部分参考这位老哥的文章 https://blog.csdn.net/weixin_39517902/article/details/111205216
CGI是common gateway interface的缩写,大家都译作通用网关接口,但很不幸,我们无法见名知意。
我们知道,web服务器所处理的内容都是静态的,要想处理动态内容,需要依赖于web应用程序,如php、jsp、python、perl等。但是web
server如何将动态的请求传递给这些应用程序?它所依赖的就是cgi协议。没错,是协议,也就是web
server和web应用程序交流时的规范。换句话说,通过cgi协议,再结合已搭建好的web应用程序,就可以让web
server也能"处理"动态请求(或者说,当用户访问某个特定资源时,可以触发执行某个web应用程序来实现特定功能),你肯定知道处理两字为什么要加上双引号。
简单版的cgi工作方式如下:
例如,在谷歌搜索栏中搜索一个关键词"http",对应的URL为:https://www.google.com/search?q=http&oq=http&aqs=chrome…69i57j69i60l4j0.1136j0j8&sourceid=chrome&ie=UTF-8
当谷歌的web
server收到该请求后,先分析该url,从中知道了要执行search程序,并且还知道了一系列要传递给search的参数及其对应的value。web
server会将这些程序参数和其它一些环境变量根据cgi协议通过TCP或套接字等方式传递给已启动的cgi程序(可能是cgi进程,或者是已加载的模块cgi模块)。当cgi进程接收到web
server的请求后,调用search程序并执行,同时还会传递参数给search程序。search执行结束后,cgi进程/线程将处理结果返回给web
server,web server再返回给浏览器。
有多种方式可以执行cgi程序,但对http的请求方法来说,只有get和post两种方法允许执行cgi脚本(即上面的search程序)。实际上post方法的内部本质还是get方法,只不过在发送http请求时,get和post方法对url中的参数处理方式不一样而已。
实验过程
在这里我新建一个文件命名为apimain.c
#include "apimain.h"
#include "httpd.h"
#include <stdio.h>static const char *api_operation_req(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]);//核心就是根据URL的参数来执行不同的处理函数
static const tCGI g_psConfigCGIURIs[] = { {"/img/sics.gif", api_operation_req},
};const char *api_operation_req(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
{// HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET);HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_3);printf("cgi success!!!!\n");
}void api_server_init(void)
{httpd_init();//这是CGI的初始化http_set_cgi_handlers(g_psConfigCGIURIs, sizeof(g_psConfigCGIURIs)/sizeof(tCGI));}
应用CGI的核心就是根据URL的参数来执行不同的处理函数,比如请求的URL是http://192.168.0.205/img/sics.gif ,我就是利用了这个GET请求,来实现一个LED灯的电平翻转,刷新网页的时候会执行这个请求。
CGI具体实现在httpd.c的http_find_file( )函数中,主要是下面几句,可以看到与URL的字符串进行对比,如果一样就进入CGI的这个句柄分支。
#if LWIP_HTTPD_CGIhttp_cgi_paramcount = -1;/* Does the base URI we have isolated correspond to a CGI handler? */if (httpd_num_cgis && httpd_cgis) {for (i = 0; i < httpd_num_cgis; i++) {if (strcmp(uri, httpd_cgis[i].pcCGIName) == 0) {/** We found a CGI that handles this URI so extract the* parameters and call the handler.*/http_cgi_paramcount = extract_uri_parameters(hs, params);uri = httpd_cgis[i].pfnCGIHandler(i, http_cgi_paramcount, hs->params,hs->param_vals);break;}}}
刷新网页请求的url是/img/sics.gif,因此我的apimain.c写的就是,这样执行这个请求的时候就会进api_operation_req()这个函数。这样我们就实现了使用网页的请求来控制单片机和其他设备。
static const tCGI g_psConfigCGIURIs[] = { {"/img/sics.gif", api_operation_req},
};
发现的问题
LWIP的HTTPD服务没有实现POST的相关处理,但是httpd.h中已经进行了声明,但是在httpd.c中没有进行具体的实现,这里坑我了一下,我没仔细看,开启LWIP_HTTPD_SUPPORT_POST的宏后,编译不过去,如果想要支持POST操作的话,要自己写函数的实现,主要是这三个函数,网上有具体的实现。
#if LWIP_HTTPD_SUPPORT_POST/* These functions must be implemented by the application *//*** @ingroup httpd* Called when a POST request has been received. The application can decide* whether to accept it or not.** @param connection Unique connection identifier, valid until httpd_post_end* is called.* @param uri The HTTP header URI receiving the POST request.* @param http_request The raw HTTP request (the first packet, normally).* @param http_request_len Size of 'http_request'.* @param content_len Content-Length from HTTP header.* @param response_uri Filename of response file, to be filled when denying the* request* @param response_uri_len Size of the 'response_uri' buffer.* @param post_auto_wnd Set this to 0 to let the callback code handle window* updates by calling 'httpd_post_data_recved' (to throttle rx speed)* default is 1 (httpd handles window updates automatically)* @return ERR_OK: Accept the POST request, data may be passed in* another err_t: Deny the POST request, send back 'bad request'.*/
err_t httpd_post_begin(void *connection, const char *uri, const char *http_request,u16_t http_request_len, int content_len, char *response_uri,u16_t response_uri_len, u8_t *post_auto_wnd);/*** @ingroup httpd* Called for each pbuf of data that has been received for a POST.* ATTENTION: The application is responsible for freeing the pbufs passed in!** @param connection Unique connection identifier.* @param p Received data.* @return ERR_OK: Data accepted.* another err_t: Data denied, http_post_get_response_uri will be called.*/
err_t httpd_post_receive_data(void *connection, struct pbuf *p);/*** @ingroup httpd* Called when all data is received or when the connection is closed.* The application must return the filename/URI of a file to send in response* to this POST request. If the response_uri buffer is untouched, a 404* response is returned.** @param connection Unique connection identifier.* @param response_uri Filename of response file, to be filled when denying the request* @param response_uri_len Size of the 'response_uri' buffer.*/
void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len);#if LWIP_HTTPD_POST_MANUAL_WND
void httpd_post_data_recved(void *connection, u16_t recved_len);
#endif /* LWIP_HTTPD_POST_MANUAL_WND */#endif /* LWIP_HTTPD_SUPPORT_POST */
总结
到此,通过这四篇文章,我实现了从零使用CUBEMX配置了一个带有FREERTOS以及LWIP和带有CGI功能的HTTPD服务器,以后如果想使用物联网设备开启局域网服务器,就可以使用这个框架。在这里我已经把框架搭好,可以根据需求进行下一步完善。
下一步我完善主要是需要与前端进行沟通,设计网页的API,如一个开门操作。通过这样的请求,利用CGI,完成比较复杂的操作。
本文提供的更多是一种思路,因为加入了操作系统,不只适用于单片机,只有是嵌入式设备都可以用,因为操作系统,lwip协议栈都是相同的。这个项目到此为止,希望有帮助的话多多点赞,收藏和评论。
CubeMX配置STM32实现httpd服务器CGI功能并使用网页控制STM32单片机(四)相关推荐
- 利用云服务器和Python架设TCP Server控制ESP8266单片机
目录 1.前言 2.控制架构 3.代码 4.控制效果 5.参考 1.前言 之前我做了个利用小爱同学+ESP8266控制电灯的装置:使用小爱同学+ESP8266+舵机控制家里的电灯_斌96的博客-CSD ...
- STM32CubeIDE开发(十), stm32的CRC计算CubeMX配置及HAL库底层实现分析
一.stm32的CRC 1.1 CRC的简介及MCU关联说明 STM32的CRC(Cyclic Redundancy Check,循环冗余校验)计算单元使用一个固定的多项式发生器,从一个32位的数据字 ...
- STM32中重映射的功能和机理
在STM32系列微控制器中,GPIO端口具有多种功能,如输入.输出.模拟输入/输出等.为了提高GPIO的灵活性和可用性,STM32系列微控制器提供了重映射(Remap)功能. 重映射功能允许将一个GP ...
- Redis配置不当可导致服务器被控制,已有多个网站受到影响 #通用程序安全预警#...
文章出自:http://news.wooyun.org/6e6c384f2f613661377257644b346c6f75446f4c77413d3d 符合预警中"Redis服务配置不当& ...
- CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC
CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC 引言 FTP代码库的移植 Cubemx配置SNTP以及RTC RTC配置方法 SNTP配置方法 FATFS载入RT ...
- c语言定时器定时1ms程序,STM32 Cubemx 配置定时器定时1mS
最近才发现原来我把定时器里的配置参数代表的意义给搞混了,这里记录一下,防止以后自己忘记. 以建立一个定时1mS定时器为例: 1.先打开定时器 2.配置好时钟 3.配置定时器设置 重点来了,以前在这里我 ...
- STM32开发(14)----CubeMX配置ADC
CubeMX配置ADC 前言 一.什么是ADC? 二.实验过程 1.单通道ADC采集 STM32CubeMX配置 代码实现 2.多通道ADC采样(非DMA) STM32CubeMX配置 代码实现 3. ...
- linux apache 404配置文件,apache httpd服务器404错误跳转配置教程
apache httpd服务器404配置是至关重要的,实现404错误页面跳转非常重要,通常情况下我喜欢在项目根目录下新建一个".htaccess"重定向配置文件,这种方式是最简单的 ...
- CentOS 7配置httpd服务器
** 配置httpd服务器 ** ##A主机部署安装httpd并利用httpd部署yum源 ###1.先关闭防火墙 systemctl stop firewalld 临时关闭防火墙 systemctl ...
最新文章
- CUDA入门需要知道的东西
- RibbonControl中的主题设计
- C#的同步和异步调用方法
- python学习高级篇(part3)--MRO
- 自行车实现无人驾驶,背后究竟有何“天机”?
- android mvvm流程图,MVVM框架模式详解
- Redis多机功能介绍
- 6大设计原则之里氏替换原则
- linux msgctl函数,msgctl()函数
- steam linux 安装目录,如何在Ubuntu中安装Steam | MOS86
- 谷歌外贸sem与百度内贸sem的不同
- ros之MarkerArray使用
- 视频批量剪辑:如何给视频添加特效,比如:色彩变幻效果特效,怎么制作?
- Revisiting Single Image Depth Estimation Toward Higher Resolution Maps
- java计算机毕业设计星星电影购票网站源码+mysql数据库+lw文档+系统+调试部署
- idea自定义archetype及错误处理
- ldap服务器的虚拟属性,搭建LDAP验证服务器
- 基于Android studio的手机联系人信息获取
- Linux如何给服务器增加白名单
- 永生源投资app想给存钱怎样存合算?看完就理解了
热门文章
- 会计学基础--试算平衡表
- Microsoft Store 访问加速教程(需科学上网)
- IDEA引入Lombok后编译时找不到符号问题处理
- 职教云python题和答案_智慧职教云课堂Python程序设计题目及答案
- 经典论文 | 300FPS,超快结构感知的深度车道检测
- Symbian操作系统及操作平台界面详解
- anaconda安装路径在Program Files下报错
- moment 取年月日_moment.js获取本周本月本年的开始日期和结束日期
- 小木的智慧屋--微信公众号的推广案例分析(1)
- 网络最强PHP开发工具+电子书+视频教程等资料下载汇总