stm32 web伺服器實現
最近在做stm32 web伺服器的東西,忙了一段時間終於弄完了,把這幾天關於stm32伺服器的工作記錄一下。
剛接到這個任務的時候,不知道怎麼下手,網上資料似乎不是很多,於是在下載了一個官方demo測試了一下,看了一下程式碼,不是很懂,於是繼續百度找資料,找到一個比較有用的網頁,以下是連結:
最近在做stm32 web伺服器的東西,忙了一段時間終於弄完了,把這幾天關於stm32伺服器的工作記錄一下。剛接到這個任務的時候,不知道怎麼下手,網上資料似乎不是很多,於是在下載了一個官方demo測試了一下,看了一下程式碼,不是很懂,於是繼續百度找資料,找到一個比較有用的網頁,以下是連結:http://wenku.baidu.com/link?url=SfAxsft0bXxvaoeDtSGCLlnB3yQNhofQfLwfO9l-aZmTsVy2haookGZI6VP4WGlnr26Fx_BxakWV3oMQbKl54FQyssKDy2fRxI5JnIXaPgK
其實,stm32 web伺服器與pc網頁的互動一般是以表單的方式,就兩個介面,cgi和ssi。這兩個東西我的理解是這樣的,cgi 就是pc網頁向stm32 web服務下發資訊的介面,比如我們有這樣的一個網頁:
<form method='get' action='config.cgi'>
<p><label for='ip'>ip:</label><input type='text' name='ip' value="<!--#ip-->" maxlength="1" /></p>
<p><
</p><p><input type='submit' value='儲存' /></p>
</form>
如果看不懂這個網頁的話,就百度一下吧,把上面東西複製到Macromedia
Dreamweaver 8軟體上就能看到是什麼頁面,上面在form就是表單,在<form></form
<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[i]/*引數名字,與網頁裡控制元件的name相同name='ip'*/,"ip")
== 0) //裝置ip
{
printf("ip is : %s \r\n",pcValue[i]/*控制元件的值*/);
}
else if(strcmp(pcParam[i],"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內容長度