1、 基于STM32的串口服务器web功能实现 编制: 陈志磊 校对: 审核: 日期: 2014-12-30 版本:V1.0 更改次数 更改时间 更改内容 版本 1 2014-12-30 初版 V1.0 说明: 本文主要说明通过web访问来配置串口服务器参数的功能,前提要求LWIP和uCOSII都已移植成功。实现B/S结构,须将串口服务器配置为web server。 一. Web Server 文件以及相关技术简
2、介 1.相关文件说明 ST公司的官网上提供了通过LWIP完成web server配置的例程,打开我们的工程文件夹“LwIP1.4.1移植STM32 V1.8”,在LWIP-APP/ web_server_demo文件夹下的文件如图所示: 各个文件的说明见下表: 文件 说明 makefsdata 该文件夹中包含有原始网页文件和将原始的网页文件转换为网页数组的工具mskefsdata.exe fs.c 用来管理生成的网页数组 fs.h fsdata.c 生成的网页数组 fsdata.h httpd.c 完成了将串口服务器配置成web server。 httpd.
3、h httpd_cgi_ssi.c CGI和SSI源文件,通过网页配置串口服务器参数主要是通过这个文件来完成 2.网页制作及网页数组数据转换 (1)网页制作 使用dreamweaver进行网页制作,交互方式主要是通过表单来完成,注意对于使用了需要使用SSI技术来嵌入数据的,需要将网页后缀设为shtml、shtm、stm等。ST的例程默认使用首页索引在httpd.c中g_psDefaultFilenames[]数组里表示,该数组如下: const default_filename g_psDefaultFilenames[] = { {"/index.shtml", false
4、 }, {"/index.ssi", true }, {"/index.shtm", true }, {"/index.html", false }, {"/index.htm", false } }; 该数据表示支持首页索引为index.shtml、index.html、index.htm的网页文件输入。在网页设计时,需考虑以下两个方面: a.表单的操作设计,表单提交的方法为post,表单的处理设为对应的CGI。 b.SSI标签的嵌入。在需要嵌入信息的位置插入SSI标签。 关于CGI和SSI稍后将会简要说明。 (2)网页数组数据转换 在 makefs
5、data 文件夹下的 fs 文件为网页源文件,如下图: 由于网页源文件不能直接放到 STM32 里面,所以要做一个转换,这里通过 makefsdata.exe 这个工具将原始网页文件转换成.c 格式的网页数组,这样就可以添加到工程中了,makefsdata 是用来将编辑好的网页文件转换成二进制数的一个工具。接下来我们讲解一下这个工具的使用方法下面我们讲解 makefsdata 工具的使用。 (1)新建一个名为 fs 的文件夹, 将编辑好的网页源文件放到 fs 文件夹下,里面包含了编辑好的 html 和.shtml 等网页文件,其中 image 文件夹里面是我们使用到的图片。 (2)将
6、 fs 文件夹和 makefsdada.exe 工具放到同一文件夹下,此处为 makefsdata 文件夹,打开 makefsdata 文件夹,如下图所示。图中的 echotool.exe 和 Tftpd32-3.51-setup.exe 为其他工具,这里没有使用到,cmd.reg 稍后我们会讲到。 (3)在 makefsdata 文件夹上点击鼠标右键,然后点击”在此位置打开 CMD”选项,打开后结果如图所示。此时会打开一个 CMD 命令窗口。如果点击右键没有”在此位置打开 CMD”选型的话,请使用makefsdata文件夹下的 cmd.reg 文件导入注册表注册,双击打开 cmd.r
7、eg,然后一路确定下去就可以了。 (4)在打开的 CMD 命令窗口中输入: makefsdata –i 命令,按回车键。就会生成fsdata.c文件,将该文件拷贝到web_server_demo文件下,然后以头文件的方式包含到工程中即可。 3.CGI技术简介 公共网关接口 CGI(Common Gateway Interface) 是 WWW 技术中最重要的技术之一,有着不可替代的重要地位。 CGI 是外部应用程序与 Web 服务器之间的接口标准,是在 CGI 程序和Web 服务器之间传递信息的规程。 CGI 规范允许 Web 服务器执行外部程序,并将它们的输出发送给 Web 浏览器
8、 CGI 在物理上是一段程序,运行在服务器上,提供同客户端 HTML 页面的 接口。 绝大多数的 CGI 程序被用来解释处理来自表单的输入信息,并在服务器产生相应的处理,或将相应的信息反馈给浏览器, CGI 程序使网页具有交互功能。比如通过web来处理提交的数据,用的就是CGI技术。CGI示意图如下: 4.SSI技术简介 服务器端嵌入: Server Side Include,是一种类似于 ASP 的基于服务器的网页制作技术。大多数的 WEB 服务器等均支持 SSI 命令。 将内容发送到浏览器之前,可以使用“服务器端包含(SSI)”指令将文本、图形或应用程序信息包含到网页中。例如
9、可以使用 SSI 包含时间/日期戳、版权声明或供客户填写并返回的表单。 对于在多个文件中重复出现的文本或图形,使用包含文件是一种简便的方法。将内容存入一个包含文件中即可,而不必将内容输入所有文件。通过一个非常简单的语句即可调用包含文件,此语句指示 Web 服务器将内容插入适当网页。而且,使用包含文件时,对内容的所有更改只需在一个地方就能完成。因为包含 SSI 指令的文件要求特殊处理,所以必须为所有 SSI 文件赋予 SSI 文件扩展名。默认扩展名是 .stm、 .shtm和 .shtml。SSI 是为 WEB 服务器提供的一套命令,这些命令只要直接嵌入到 HTML 文档的注释内容之中即可。
10、如: 就是一条 SSI 指令,其作用是将"info.htm"的内容拷贝到当前的页面中,当访问者来浏览时,会看到其它 HTML 文档一样显示 info.htm 其中的内。 在本项目中,将串口服务器的配置信息通过SSI嵌入的方式来显示到网页上,还有一种比较高效的交互方式,即通过ajax来实现异步交互,有兴趣可以研究下。 二. 软件设计 前面介绍过,fs.c 文件管理生成的网页数组文件这个文件由 ST 提供。 httpd.c 文件是本章实验的重点, 这个文件将开发板配置为 Web Server,这个文件也由 ST 官方提供的,
11、阅读这个文件需要有网页相关的知识,这里对这个文件不做讲解。 当在浏览器中输入网址, web服务器就会返回给我们相应的网页,然后浏览器解析并呈现给我们。同样的,当我们通过浏览器访问开发板的时候,开发板这时是作为服务器的,服务器针对不同的 URL 在 fsdata.c 文件中找出相应的网页,并且返回给浏览器, 在 fsdata.c 文件中查找网页的过程就需要 fs.c 里面的函数。 接收浏览器发送的数据并且将网页返回给浏览器的过程都是由 httpd.c 文件里面的函数来完成的。 1.POST方法实现 ST的例程中默认使用的是GET方法,而在提交用户名和密码等数据时,希望安全性更高;在提交串口
12、服务器的配置信息时,信息比较多,也不希望全部添加到URL中,综上考虑,选择使用POST方式来提交表单。因此需要对httpd.c和httpd.h文件做一些修改。 (1)修改httpd.h文件中的宏定义LWIP_HTTPD_SUPPORT_POST,使其支持POST方法。 /** 设置为1支持POST Set this to 1 to support HTTP POST */ #ifndef LWIP_HTTPD_SUPPORT_POST #define LWIP_HTTPD_SUPPORT_POST 1 #endif (2)实现三个函数,关于这三个函数的详细代码,请参考httpd
13、c文件。 a.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); b.err_t httpd_post_receive_data(void *connection, s
14、truct pbuf *p); c.void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len); 2.GCI实现 通过表单提交的不同CGI来执行对应的handler函数,在 httpd_cgi_ssi.c 中我们定义了一个数组 ppcURLS,数组如下: static const tCGI ppcURLs[]= //cgi程序 { {"/login.cgi",Login_CGIHandler },//文件名 文件功能 {"/write.cgi",WEBSET_C
15、GIHandler },//文件名 文件功能 {"/setpwd.cgi",SetPwd_CGIHandler },//文件名 文件功能 {"/uart.cgi",SetUart_CGIHandler},//文件名 文件功能 }; 关于以上几个cgi说明如下表: CGI Handler函数 说明 /login.cgi Login_CGIHandler 登录配置 /write.cgi WEBSET_CGIHandler 串口服务器参数配置 /setpwd.cgi SetPwd_CGIHandler 登录密码更改 /uart.cgi SetUart_CGI
16、Handler 串口参数配置 当接收到/login.cgi时,就会执行Login_CGIHandler函数,该函数代码如下: //登录的CGI控制句柄 const char* Login_CGIHandler(int iIndex,int iNumParams,char *pcParam[],char *pcValue[]) { int index; index = FindCGIParameter ( "name", pcParam, iNumParams ); if(index!=-1) { if(strcmp(pcValue[index],l
17、wip_login.username) != 0)//用户名不相等 return "/index.shtml"; } index = FindCGIParameter ( "password", pcParam, iNumParams ); if(index!=-1) { if(strcmp(pcValue[index],lwip_login.passwd) != 0)//密码不相等 return "/index.shtml"; } return "/lwipset.shtml"; //这里返回你要发给浏览器的文件名
18、路径 } 从上面的代码可以看出,通过web浏览器提交的表单项名称依次存放在pcParam中,表单项内容依次存放在pcValue中,iNumParams存放的是提交的数据个数。在Login_CGIHandler中,首先判断是否提交了“name”和“passward”这些表单标签,然后判断用户名和密码是否相等,如果相等,则进入串口服务器配置界面,否则,登录不成功。 其余几个handler函数的原理一样,不再赘述。 3.SSI实现 这里通过SSI来实现配置信息的显示,如下图: 要实现SSI,必须在制作网页时,在对应的需要显示的位置添加SSI标签,然后在程序检测该标签,从而嵌入对应的数
19、据。 SSIHandler 函数为 SSI 的句柄函数,函数代码如下, 在这个函数中我们根据参数 iIndex 调 用不同的函数来完成向网页中添加数据,这几个函数比较简单。 在httpd_cgi_ssi.c文件中,SSI标签数据定义如下: //SSI插入标签 static const char *ppcTAGs[]= //SSI的Tag { "e", //登录错误 "h", //IP模式 "i", //IP地址 "j", //端口 "k", //工作模式 "l", //子网掩码 "m", //网关 "n",//目的IP "o", //目
20、的端口 "w", //波特率 "x", //数据位 "y", //校验位 "z", //停止位 }; SSIHandler函数代码如下,该函数通过判断SSI标签ppcTAGs来在不同的位置插入对应的信息。 //SSI的Handler句柄 //根据不同的索引来插入对应的数据 //返回:插入数据的字符串长度 static u16_t SSIHandler(int iIndex,char *pcInsert,int iInsertLen) { char *p; switch(iIndex) { case 0: //登录错误 p =
21、 "用户名或密码错误!!!"; WEB_dis_Handler(pcInsert,p); break; case 1://IP获取方式 if(lwipdev.dhcp_enable) p = "动态获取"; else p = "静态"; WEB_dis_Handler(pcInsert,p); break; case 2://ip地址 WEB_dis_Handler(pcInsert,pIp_addr); break; case 3://端口 WEB_dis_H
22、andler(pcInsert,pIp_Localport); break; case 4://工作模式 if(lwipdev.tcp_mode == TCP_SERVER_MODE) p = "TCP server"; else p = "TCP client"; WEB_dis_Handler(pcInsert,p); break; …… } 4.初始化 当完成以上步骤后,还需要完成CGI和SSI的初始化,分别调用http_set_cgi_handler
23、s()和http_set_ssi_handler()来完成,代码如下: //SSI句柄初始化 void httpd_ssi_init(void) { //配置内部温度传感器的SSI句柄 http_set_ssi_handler(SSIHandler,ppcTAGs,NUM_CONFIG_SSI_TAGS); } //CGI句柄初始化 void httpd_cgi_init(void) { //配置CGI句柄LEDs control CGI) */ http_set_cgi_handlers(ppcURLs, NUM_CONFIG_CGI_URIS);
24、} 最后,在系统初始化时,调用 httpd_init()函数进行整个web server的初始化,该函数包含了上面的CGI和SSI初始化。该函数代码如下: //初始化httpd,建立一个监听PCB并且绑定到指定的端口上 void httpd_init(void) { LWIP_DEBUGF(HTTPD_DEBUG, ("httpd_init\n")); #if LWIP_HTTPD_SSI httpd_ssi_init(); #endif #if LWIP_HTTPD_CGI httpd_cgi_init(); #endif httpd_
25、init_addr(IP_ADDR_ANY); } 经过以上步骤,串口服务器就可以通过web浏览器访问来配置了。 三. 下载验证 在代码编译成功以后,下载代码到串口服务器中,通过网线连接开发板到路由器或者交换机上,如果没有路由器的话就连接到电脑端的 RJ45 上,可以配置为DHCP来获取IP地址,当获取到当前的IP地址后,就可以通过这个IP来进行web访问了。如下图所示: 如果拥有域名的话,还可以将域名解析到这个web server的IP,就可以实现通过域名来访问了。如下图所示: 登录成功的界面如下所示: 可以看到当前串口服务器的配置信息,并且可以修改它。当设置成功后,会弹出提示页面:






