图解丨在嵌入式设备上实现HTTP服务器
您好呀,我是小二。
本期為大家?guī)硪粋€(gè) WiFi 應(yīng)用的實(shí)際場景,其實(shí)在之前「我對(duì) WiFi 驅(qū)動(dòng)移植過程,做了一次總結(jié)復(fù)盤」這篇文章中有簡單提過,但由于內(nèi)容較多,就單獨(dú)摘出來了。
來自讀者的催更????????????,別著急,小二在努力了!
1 應(yīng)用場景
我喜歡講一個(gè)東西,先來探討下他的應(yīng)用場景。
畢竟知道了用在哪,怎么用,才能寫好代碼嘛,哈哈????
本次項(xiàng)目,實(shí)際的應(yīng)用場景:通過手機(jī) APP ,連接到設(shè)備 WiFi 熱點(diǎn),進(jìn)行設(shè)備的參數(shù)配置;
接著結(jié)合實(shí)際框架,拆分需求如下:
采用 HTTP 協(xié)議,使用 POST 方法;
設(shè)備端需要作為一個(gè) HTTP 服務(wù)器;
不需要支持 CGI ,通過 APP 展示界面即可;
好了,明白了需求,接下來就是實(shí)現(xiàn)方案了。
2 方案論證
剛開始的時(shí)候,一點(diǎn)頭緒都沒有。
組長指導(dǎo)的一種方案,就是在新唐數(shù)據(jù)手冊(cè)中看到的,采用 Lighttpd 的方案。
后來去查資料,發(fā)現(xiàn)一篇介紹不同 HTTP 服務(wù)器的文章,挺不錯(cuò)的,如下
常見的幾種嵌入式web服務(wù)器(https://www.cnblogs.com/quliuliu2013/p/12786301.html)
2.1 Lighttpd
這塊剛開始是同事在搞,后來我這邊的需求規(guī)劃出來后,就在想能否使用這種方案。
畢竟方案是現(xiàn)成的,可以節(jié)省不少時(shí)間。
后來經(jīng)過分析,發(fā)現(xiàn) Lighttpd 需要一個(gè)單獨(dú)的進(jìn)程執(zhí)行,如下圖所示
Lighttpd 提供了 CGI 接口,支持 IE 訪問固定界面,然后進(jìn)行參數(shù)配置。
實(shí)際實(shí)現(xiàn)方案,我認(rèn)為比較好的方法是,Lighttpd 進(jìn)程接收到參數(shù)變更時(shí),寫入配置文件 A ,主業(yè)務(wù)進(jìn)程監(jiān)測文件 A 是否有改變,如果檢測到改變,則讀一次數(shù)據(jù)。
具體實(shí)現(xiàn)方式,參考下圖
結(jié)合實(shí)際情況分析,
1、目前只維護(hù)一個(gè)主業(yè)務(wù)進(jìn)程,如果再增加額外的進(jìn)程,則維護(hù)成本將大大增加。
2、實(shí)際不需要 CGI 接口,不需要支持 IE ,APP 做界面顯示即可。
經(jīng)過論證,此方案較復(fù)雜,暫且當(dāng)做最后的備選方案。
2.2 cpp-httplib
接著我就去 GitHub 上尋找 HTTP Server ,發(fā)現(xiàn) cpp-httplib 這個(gè)比較好用的庫。
GitHub 鏈接:cpp-httplib(https://github.com/yhirose/cpp-httplib)
在查看了 ReadMe 文件后,很遺憾,我用不了????????????
提示說 GCC 4.8 及以下版本無法正常編譯,因?yàn)?<regex> 文件已損壞。。。
我去找了找解決方法,發(fā)現(xiàn)在 GCC 4.9 版本修復(fù)了這個(gè)問題,參考 Stack Overflow 回答如下
https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions
沒辦法了,我們當(dāng)前 GCC 版本是 4.8.3 的,肯定不能因?yàn)檫@個(gè)庫就更換編譯器呀,那只能再去找找看咯。
2.3 httpserver
然后就接著去搜索,發(fā)現(xiàn)了 httpserver 這個(gè)庫,只有一個(gè) .h 頭文件,感覺很簡單。
GitHub 鏈接:httpserver(https://github.com/jeremycw/httpserver.h)
分析本質(zhì)需求,發(fā)現(xiàn)只需要在主進(jìn)程中,跑一個(gè) HTTP Server 的線程,監(jiān)聽固定端口,然后采用 HTTP 協(xié)議進(jìn)行通信即可。
簡要功能,如下圖所示
從上圖可以看出
1、主進(jìn)程中,單獨(dú)跑一個(gè) HTTP Server 的線程,監(jiān)聽固定端口 8888 ;
2、此線程同時(shí)進(jìn)行數(shù)據(jù)處理,將參數(shù)寫入文件 A ;
3、其他業(yè)務(wù)線程,在需要參數(shù)時(shí),直接去文件 A 獲取最新參數(shù)即可;
3 實(shí)現(xiàn)方式
具體實(shí)現(xiàn)方式,參考 ReadMe 文件,也很方便實(shí)現(xiàn)。
簡述一下主要流程:
綁定監(jiān)聽端口號(hào),綁定回調(diào)函數(shù);
死循環(huán)監(jiān)聽端口;
當(dāng)需要關(guān)閉 HTTP 服務(wù)時(shí),通過 flag 標(biāo)志位,改變當(dāng)前狀態(tài);
關(guān)閉 HTTP 服務(wù)后,需要釋放相應(yīng)資源;
所有的配置處理接口,在 HandleRequest 回調(diào)函數(shù)中;
(PS:我這電腦網(wǎng)絡(luò)有問題,GitHub 一直打不開,手機(jī)熱點(diǎn)也不行,暫時(shí)還沒別的好辦法,只能麻煩您自己去網(wǎng)頁上看啦。)
4 注意事項(xiàng)
在使用過程中,我這遇到一個(gè)問題。
您看下邊這塊代碼,是這樣的
void?hs_init_session(http_request_t*?session)?{session->flags?=?HTTP_AUTOMATIC;session->parser?=?(http_parser_t){};session->stream?=?(hs_stream_t){};if?(session->tokens.buf)?{free(session->tokens.buf);session->tokens.buf?=?NULL;}http_token_dyn_init(&session->tokens,?32); }在第 3 、4 行末尾,直接就是一個(gè)大括號(hào),里邊什么都沒寫。
然后我的程序在這個(gè)地方就一直編譯不過去。后來在公司前輩指點(diǎn)下,按照下圖所示,添加了 0 之后,就能編譯通過了。
推測原因是當(dāng)前編譯器使用的 C 標(biāo)準(zhǔn),不支持這么高級(jí)的用法。
注意:需要修改的不止這一處,其他地方如有編譯報(bào)錯(cuò),也需做類似修改。
5 總結(jié)
針對(duì)本次的功能需求,最困難的地方,在于尋找一個(gè)合適的 HTTP Serve 庫來使用。
過程雖然艱難,但也鍛煉了自己找東西的能力。
好了各位看官,本次的分享到此結(jié)束,如果您還意猶未盡,大可從頭再看。
最后別忘了賞小二一個(gè) 贊 和 在看 哦????????????
祝您端午安康,工作順利!
推薦閱讀:
專輯|Linux文章匯總
專輯|程序人生
專輯|C語言
我的知識(shí)小密圈
關(guān)注公眾號(hào),后臺(tái)回復(fù)「1024」獲取學(xué)習(xí)資料網(wǎng)盤鏈接。
歡迎點(diǎn)贊,關(guān)注,轉(zhuǎn)發(fā),在看,您的每一次鼓勵(lì),我都將銘記于心~
嵌入式Linux
微信掃描二維碼,關(guān)注我的公眾號(hào)
總結(jié)
以上是生活随笔為你收集整理的图解丨在嵌入式设备上实现HTTP服务器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件测试基础知识总结
- 下一篇: kuangbin专题-简单搜索