最近在做stm32 web服务器的东西,忙了一段时间终于弄完了,把这几天关于stm32服务器的工作记录一下。 刚接到这个任务的时候,不知道怎么下手,网上资料似乎不是很多,于是在下载了一个官方demo测试了一下,看了一下代码,不是很懂,于是继续百度找资料,找到一个比较有用的网页,以下是链接: 最近在做stm32 web服务器的东西,忙了一段时间终于弄完了,把这几天关于stm32服务器的工作记录一下。刚接到这个任务的时候,不知道怎么下手,网上资料似乎不是很多,于是在下载了一个官方demo测试了一下,看了一下代码,不是很懂,于是继续百度找资料,找到一个比较有用的网页,以下是链接:http://wenku.baidu.com/link?url= ... ssKDy2fRxI5JnIXaPgK 其实,stm32 web服务器与pc网页的交互一般是以表单的方式,就两个接口,cgi和ssi。这两个东西我的理解是这样的,cgi 就是pc网页向stm32 web服务下发信息的接口,比如我们有这样的一个网页: <formmethod='get'action='config.cgi'> <p><labelfor='ip'>ip:</label><input type='text' name='ip' value="<!--#ip-->" maxlength="1" /></p> <p><labelfor='port'>port:</label><input type='text' name='port' value="<!--#port-->" maxlength="6" /> </p><p><inputtype='submit'value='保存'/></p> </form> 如果看不懂这个网页的话,就百度一下吧,把上面东西复制到Macromedia Dreamweaver 8软件上就能看到是什么页面,上面在form就是表单,在<form></form>里面的内容就是表单的内容,里面有两个输入框,和一个保存按钮,当我们点出保存的时候就会在web服务器里触发,config.cgi的接口,关于web服务器的内容,后面再说,然后会把这个表单里的内容下发到服务器里,比如会把上面ip和port输入框中的数据发到web服务器里,web服务器就能获得想要的数据。接下来说一下ssi,我们可以拿个网络抓包软件观察一下,pc网页的web服务器的通信过程,其实也就是pc发送一个请求,然后web服务器返回一组数据,这组数据就是整个网页的内容。ssi的工作就是在这组返回的数据中嵌入一个要发送加pc端的数据在里面,比如刚才那个表单网页数据,我们要显示一些数据到ip输入框中,怎么办呢?在没有ssi接口的时候可以看到, <p><labelfor='ip'>ip:</label><input type='text' name='ip' value="<!--#ip-->" maxlength="1" /></p> , 有ssi接口时候,我们就可以利用ssi接口改变返回的内容,比如: <p><labelfor='ip'>ip:</label><input type='text' name='ip' value="<!--#ip-->192.168.1.1" maxlength="1" /></p>, 可以看到 "<!--#ip-->192.168.1.1" 这个地方是不相同的,这时返回ip输入框是带着数据的,这个数据将显示在ip输入框内。 接下来分析一下代码,首先看一下stm32官方http web 包里的文件 
fsdata.c,fsdata.h,是网页转换成的数组, fs.c, fs.h是操作fsdata.c里面数据的一些读写函数 httpd.c, httpd.h函数是真正实现web服务器的文件 httpd_cgi_ssi.c, httpd_cgi_ssi.h 就是刚才提到的cgi, ssi接口, 一般我们只需要改动httpd_cgi_ssi.c,fsdata.c(这个文件是makefsfile.exe生成的), makefsfile里面又有一些什么文件呢 
fs文件夹是所有的网页,fsdata.c 是用makefsfile.exe转换得到的 下面分析一下代码 1. void httpd_init(void)
{
LWIP_DEBUGF(HTTPD_DEBUG, ("httpd_init\n"));
#if LWIP_HTTPD_SSI
httpd_ssi_init(); //ssi接口初始化
#endif
#if LWIP_HTTPD_CGI
httpd_cgi_init(); //cgi接口初始化
#endif
httpd_init_addr(IP_ADDR_ANY); //http web 相关初始化
} 2.ssi接口 要注意的一点就是 有ssi接口的网页要以 shtml为后缀 char const* TAGS[]={ //这里定义了ssi标签,
"ip", //ip地址 对应网页里的<!--#ip-->
"sp", //服务器端口
};
u16_t DeviceSSI_Handler(int iIndex, char *pcInsert, int iInsertLen)
{
int len = 0;
char buff[16];
memset(buff,0,sizeof(buff));
switch(iIndex)
{
case 0: //这个index是在数组中的位置
sprintf(buff,"%s",“192.168.1.1”);
len = strlen(buff);
memcpy(pcInsert,buff,len);// 这里是拷贝填充在ip标签里的内容 break;
case 1: 。。。。。。 break; } return len; } 3.cgi接口 //cgi接口定义
tCGI CGI_TAB[]={
{"/login.cgi", LOGIN_CGI_Handler},
{"/saveNet.cgi", SAVE_NET_Handler} /*这里的cginame要和网页表单里的action相同<formmethod='get'action='config.cgi'>*/
}; const char * SAVE_NET_Handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
{
uint32_t i=0;
for (i=0; i<iNumParams/*参数数量*/; i++)
{
if(strcmp(pcParam/*参数名字,与网页里控件的name相同name='ip'*/,"ip") == 0) //设备ip
{ printf("ip is : %s \r\n",pcValue/*控件的值*/);
}
else if(strcmp(pcParam,"port") == 0)
{
... } ...... } cgi和ssi大概就这些内容要改的, 4.打开网页里是哪一个为首页呢?在httpd.c里有一个数据 //这里设置首页显示的html ,所以首页就是login
const default_filename g_psDefaultFilenames[] = {
{"/login.shtml", true },
{"/login.ssi", true },
{"/login.shtm", true },
{"/login.html", false },
{"/login.htm", false }
};
5.我们发送ssi标签时会把标签一起发上去,这样在编辑控件里是会把标签一起显示的,比如value="<!--ip-->192.168.1.1",这不是我们想要的,怎么让它不发送标签呢, 把httpd.c里的定义 #define LWIP_HTTPD_SSI_INCLUDE_TAG 1 //改为0就不发送标签 6.还有一些比较常用的宏定义 #define LWIP_HTTPD_MAX_CGI_PARAMETERS 16 //cgi数量定义
#define LWIP_HTTPD_MAX_TAG_NAME_LEN 8 //定义tag标签长度定义
#define LWIP_HTTPD_MAX_TAG_INSERT_LEN 192 //定义返回tag内容长度 更多嵌入式视频尽在:www.makeru.com.cn/?t=12 嵌入式学习交流群:561213221
|