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单片机(四)相关推荐

  1. 利用云服务器和Python架设TCP Server控制ESP8266单片机

    目录 1.前言 2.控制架构 3.代码 4.控制效果 5.参考 1.前言 之前我做了个利用小爱同学+ESP8266控制电灯的装置:使用小爱同学+ESP8266+舵机控制家里的电灯_斌96的博客-CSD ...

  2. STM32CubeIDE开发(十), stm32的CRC计算CubeMX配置及HAL库底层实现分析

    一.stm32的CRC 1.1 CRC的简介及MCU关联说明 STM32的CRC(Cyclic Redundancy Check,循环冗余校验)计算单元使用一个固定的多项式发生器,从一个32位的数据字 ...

  3. STM32中重映射的功能和机理

    在STM32系列微控制器中,GPIO端口具有多种功能,如输入.输出.模拟输入/输出等.为了提高GPIO的灵活性和可用性,STM32系列微控制器提供了重映射(Remap)功能. 重映射功能允许将一个GP ...

  4. Redis配置不当可导致服务器被控制,已有多个网站受到影响 #通用程序安全预警#...

    文章出自:http://news.wooyun.org/6e6c384f2f613661377257644b346c6f75446f4c77413d3d 符合预警中"Redis服务配置不当& ...

  5. CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC

    CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC 引言 FTP代码库的移植 Cubemx配置SNTP以及RTC RTC配置方法 SNTP配置方法 FATFS载入RT ...

  6. c语言定时器定时1ms程序,STM32 Cubemx 配置定时器定时1mS

    最近才发现原来我把定时器里的配置参数代表的意义给搞混了,这里记录一下,防止以后自己忘记. 以建立一个定时1mS定时器为例: 1.先打开定时器 2.配置好时钟 3.配置定时器设置 重点来了,以前在这里我 ...

  7. STM32开发(14)----CubeMX配置ADC

    CubeMX配置ADC 前言 一.什么是ADC? 二.实验过程 1.单通道ADC采集 STM32CubeMX配置 代码实现 2.多通道ADC采样(非DMA) STM32CubeMX配置 代码实现 3. ...

  8. linux apache 404配置文件,apache httpd服务器404错误跳转配置教程

    apache httpd服务器404配置是至关重要的,实现404错误页面跳转非常重要,通常情况下我喜欢在项目根目录下新建一个".htaccess"重定向配置文件,这种方式是最简单的 ...

  9. CentOS 7配置httpd服务器

    ** 配置httpd服务器 ** ##A主机部署安装httpd并利用httpd部署yum源 ###1.先关闭防火墙 systemctl stop firewalld 临时关闭防火墙 systemctl ...

最新文章

  1. CUDA入门需要知道的东西
  2. RibbonControl中的主题设计
  3. C#的同步和异步调用方法
  4. python学习高级篇(part3)--MRO
  5. 自行车实现无人驾驶,背后究竟有何“天机”?
  6. android mvvm流程图,MVVM框架模式详解
  7. Redis多机功能介绍
  8. 6大设计原则之里氏替换原则
  9. linux msgctl函数,msgctl()函数
  10. steam linux 安装目录,如何在Ubuntu中安装Steam | MOS86
  11. 谷歌外贸sem与百度内贸sem的不同
  12. ros之MarkerArray使用
  13. 视频批量剪辑:如何给视频添加特效,比如:色彩变幻效果特效,怎么制作?
  14. Revisiting Single Image Depth Estimation Toward Higher Resolution Maps
  15. java计算机毕业设计星星电影购票网站源码+mysql数据库+lw文档+系统+调试部署
  16. idea自定义archetype及错误处理
  17. ldap服务器的虚拟属性,搭建LDAP验证服务器
  18. 基于Android studio的手机联系人信息获取
  19. Linux如何给服务器增加白名单
  20. 永生源投资app想给存钱怎样存合算?看完就理解了

热门文章

  1. 会计学基础--试算平衡表
  2. Microsoft Store 访问加速教程(需科学上网)
  3. IDEA引入Lombok后编译时找不到符号问题处理
  4. 职教云python题和答案_智慧职教云课堂Python程序设计题目及答案
  5. 经典论文 | 300FPS,超快结构感知的深度车道检测
  6. Symbian操作系统及操作平台界面详解
  7. anaconda安装路径在Program Files下报错
  8. moment 取年月日_moment.js获取本周本月本年的开始日期和结束日期
  9. 小木的智慧屋--微信公众号的推广案例分析(1)
  10. 网络最强PHP开发工具+电子书+视频教程等资料下载汇总