從頭搭建一個嵌入式web服務器-boa服務器


一、什么是boa?

BOA是一款非常小巧的Web服務器,源代碼開放、性能優秀、支持CGI通用網關接口技術,特別適合應用在嵌入式系統中。

BOA服務器主要功能是在互聯嵌入式設備之間進行信息交互,達到通過網絡對嵌入式設備進行監控,並將反饋信息自動上傳給主控設備的目的。它是基於HTTP超文本傳輸協議的,Web網頁是Web服務最基本的傳輸單元。

嵌入式Web服務的工作基於客戶機/服務器計算模型,由Web瀏覽器(客戶機)和Web服務器(服務器)構成,也即著名的B/S結構。運行於客戶端的瀏覽器首先要與嵌入式Web服務器BOA端建立連接,打開一個套接字虛擬文件,此文件建立標志着SOCKET連接建立成功然后客戶端瀏覽器通過套接字SOCKET以GET或者POST參數傳遞方式向Web服務器提交請求,Web瀏覽器提交請求后,通過HTTP協議傳送給Web服務器。Web服務器接到請求后,根據請求的不同進行事務處理,返回HTML文件或者通過CGI調用外部應用程序,返回處理結果。

服務器通過CGI與外部應用程序和腳本之間進行交互,根據客戶端瀏覽器在請求時所采用的方法,服務器會搜集客戶所提供的信息,並將該部分信息發送給指定的CGI擴展程序,CGI擴展程序進行信息處理並將結果返回給服務器,然后服務器對信息進行分析,並將結果發送回客戶端在瀏覽器上顯示出來。

二、boa移植步驟

平台:ubuntu 16.04
版本是:boa-0.94.13.tar.gz

1. 下載地址:

http://www.boa.org/

服務器已經無法訪問,可以公號后台回復關鍵字:boa,獲取壓縮包

2. 源碼解壓

源代碼拷貝到:

/home/peng/boa
peng@ubuntu:~/boa$ tar -xf boa-0.94.13.tar.gz 

3. 安裝詞法解析器

$ sudo apt-get install bison
$ sudo apt-get install flex

yacc是一個文法分析器的生成器,bison即是yacc的GNU版本
Lex和YACC是用於構造詞法分析機和語法解釋器的工具,利用Lex和YACC你可以輕松的構造一個語法解釋器。

4. 修改編代碼

  1. src/compat.h
    打開文件
src/compat.h

修改

120: #define TIMEZONE_OFFSET(foo) foo##->tm_gmtoff

120: #define TIMEZONE_OFFSET(foo) (foo)->tm_gmtoff
  1. src/log.c
    打開文件:
src/log.c


3. boa.c

5. 編譯

peng@ubuntu:~/boa/boa-0.94.13$ cd src/
peng@ubuntu:~/boa/boa-0.94.13/src$ ./configure --prefix=/home/peng/boa/boa-0.94.13/tmp

peng@ubuntu:~/boa/boa-0.94.13/src$ make
peng@ubuntu:~/boa/boa-0.94.13/src$ sudo mkdir /etc/boa
peng@ubuntu:~/boa/boa-0.94.13/src$ sudo cp ../boa.conf /etc/boa

6. 修改配置文件boa.conf

修改AccessLog /var/log/boa/access_log
為#AccessLog /var/log/boa/access_log

其中,#表示注釋,在文件內部,我們找到#后面的內容,然后加上#下面的內容即可。

Boa Webserver配置參數說明:

Port:boa服務器監聽的端口,默認的端口是80。如果端口小於1024,則必須是root用戶啟動服務器。

Listen:綁定的ip地址。不使用這個參數時,將綁定所有的地址。

User:連接到服務器的客戶端的身份,可以是用戶名或UID。(為什么非要指定為文件的所有者才能訪問網頁呢?nobody用戶也有讀權限啊)

Group:連接到服務器的客戶端的組,可以是組名或GID。

ServerAdmin:服務器出故障時要通知的郵箱地址。

ErrorLog:指定錯誤日志文件。如果路徑沒有以“/”開始,則相對於ServerRoot路徑。沒有配置時默認的文件是/dev/stderr。若不想記錄日志,指定文件為/dev/null。

AccessLog:設置存取日志文件,與ErrorLog類似。

UseLocaltime:設置使用本地時間,使用UTC時注釋這個參數。這個參數沒有值。

VerboseCGILogs:在錯誤日志文件中記錄CGI啟動和停止時間,若不記錄,注釋這個參數。這個參數沒有值。

ServerName:指定服務器的名稱,當客戶端使用gethostname + gethostbyname時返回給客戶端。

VirtualHost:虛擬主機開關。使用此參數,則會在DocumentRoot設定的目錄添加一個ip地址作為新的DocumentRoot來處理客戶端的請求。如DocumentRoot設置為/var/www,則http://localhost/ 則轉換成/var/www/127.0.0.1/,若注釋此參數,則為/var/www/。
DocumentRoot:HTML文件的根目錄(也就是網站的目錄)。
UserDir:指定用戶目錄。

DirectoryIndex:指定預生成目錄信息的文件,注釋此變量將使用DirectoryMaker變量。這個變量也就是設置默認主頁的文件名。

DirectoryMaker:指定用於生成目錄的程序,注釋此變量將不允許列目錄。

DirectoryCache:當DirectoryIndex文件不存在,而DirecotryMaker又被注釋掉時,將列出這個參數指定目錄給客戶端。

KeepAliveMax:每個連接允許的請求數量。如果將此值設為" 0 ",將不限制請求的數目。

KeepAliveTimeOut:在關閉持久連接前等待下一個請求的秒數。(秒)。

MimeTypes:設置包含mimetypes信息的文件,一般是/etc/mime.types。

DefaultType:默認的mimetype類型,一般是text/html。
CGIPath:相當於給CGI程序使用的$PATH變量。
SinglePostLimit:一次POST允許最大的字節數,默認是1MB.
AddType: 增加MimeType沒有指定的類型,例: AddType type extension [extension ...]。要使用cgi,必須添加cgi類型:AddType application/x-httpd-cgi cgi
Redirect:重定向文件
Aliases:指定路徑的別名。

ScriptAlias:指定腳本路徑的虛擬路徑。

三、運行測試

  1. 在 /www下新建index.html文件,並放置名為yikou.png的圖片到image目錄下。
    文件目錄如下:
root@ubuntu:/www# tree ./
./
├── image
│   └── yikou.png
└── index.html

1 directory, 2 files

index.html內容

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" >
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>一口Linux</title>
</head>
<body  >
<div align="center">
	<table width="900" border="0">
	  <tr><td>
	   <form  onsubmit="return isValidate(myform)" action="cgi-bin/login.cgi" method="post">
		用戶名: <input type="text" name="username" id="username" > 
		<td>&nbsp;</td>
		  <tr><td>
		密  &nbsp;&nbsp;碼: <input type="password" name="userpass" id="userpass"> 
			<td>&nbsp;</td>
		  <tr><td>
		<input type="submit" value="登錄" id="button"  >
			</form>

			</td></tr>
	</table>
</div>

   <div align="center">
    <table width="900" height="467" border="0" background="./image/yikou.png">
      <tr>
        <td width="126" height="948">&nbsp;</td>
        <td width="351"></td>
        <td width="101">&nbsp;</td>
      </tr>  
  </div>
</body>
</html>

關於html語法,后面一口君會寫幾篇入門的教程。

  1. 運行boa
root@ubuntu:/home/peng/boa/boa-0.94.13/src# ./boa
root@ubuntu:/home/peng/boa/boa-0.94.13/src# [29/Jan/2022:15:42:26 +0000] boa: server version Boa/0.94.13
[29/Jan/2022:15:42:26 +0000] boa: server built Jan 29 2022 at 07:42:23.
[29/Jan/2022:15:42:26 +0000] boa: starting server pid=5761, port 80
  1. 打開瀏覽器

輸入地址:

http://192.168.174.128/

只要能ping通boa所在主機的ip地址的瀏覽器都可以訪問。

四、錯誤匯總

1.必需要在板子的/etc下建一個boa目錄(錯誤代碼忘了)

2.”can't open boa.conf for reading“
解決:不只要在你本身放置boa的目錄下放入boa.conf配置文件,並且要在板子的/etc/boa下也要放入boa.conf文件,這樣系統在運行boa的時候才能夠讀取到boa.conf文件。

3.“unable to dup2 the error log bad file descriptor”
解決:在boa源碼里,即src文件夾下把log.c中的第73行的if語句注釋掉。

4."unable to dup2 the error log:Bad file descriptor"
解決:在boa.conf里,把“#AccessLog /var/log/boa/access_log”注釋掉(即去掉#號)。

5.“[01/Jan/2031:00:12:25 +0000] boa.c:226 - icky Linux kernel bug!: No such file or directory”
解決:在boa源碼里,即src文件夾下把boa.c中的第226行的if語句注釋掉。

6."gethostbyname:: Resource temporarily unavailable"
解決:把“#ServerName www.your.org.here”的“#”號去掉。

7."./boa: 1: syntax error: "(" unexpected"
解決:沒有修改Makefile,是用gcc編譯的,應該改為是arm-linux-gcc編譯。

8.若是頁面上是:“502 Bad Gateway The CGI was not CGI/1.1 compliant.“
解決:給你要執行的cgi可執行程序賦個權限。chmod 777 filename

9.在

中,cgi可執行程序的路徑就直接寫“cgi-bin/test2.cgi”就能夠了,不要寫板子上的絕對路徑,這樣就重復了,由於cgi執行時會自動去boa.conf的指定的路徑里找。

10.出現警告:“control reaches end of non-void function”,是由於某個函數沒有return,而函數定義時是非void型的。因此須要有個返回值。好比int cgiMain()這個函數就必定要有個返回值的,不然會報這個錯誤。

11.運行網頁時老出現錯誤:“mkstemp:No such file or diectory”
解決:不能用post,只能用get。由於post方式須要新建一個臨時文件,這就須要用到mkstemp函數。這個函數是在系統中以惟一的文件名建立一個文件並打開,且只有當前用戶才能訪問這個臨時文件。故權限不夠,或其余什么問題都會報這個錯誤。那么就用get吧!這里具體緣由細節筆者暫時也不是很清楚...

12.直接寫的含有system()函數的c程序用arm-linux-gcc編譯到板子上的能夠執行,而若是寫在cgi中的就不必定能執行了。由於牽涉到一個cgi的權限的問題。即便給你的cgi-bin文件夾下的全部cgi可執行文件都賦了權限,也不必定能執行。

解決辦法就是看看你的boa.conf中的權限設置的如何。這里正確的應該是把“User nobody Group nogroup”改成“User root Group 0”,不然不能正確執行!你會發現你的cgi可執行程序的其余代碼都執行了,卻只有這個system()函數沒有執行!

五、修改的參數說明

(1)Group的修改:

修改 Group nogroup
為 Group 0
Group表示連接到服務器的客戶端的組,可以是組名或GID。

(2)user的修改

修改 User nobody
為 User 0
User:連接到服務器的客戶端的身份,可以是用戶名或UID。

(3)ScriptAlias的修改

修改ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
為 ScriptAlias /cgi-bin/ /www/cgi-bin/
ScriptAlias:指定腳本路徑的虛擬路徑。

(4)DocumentRoot的修改

修改DocumentRoot /var/www
為DocumentRoot /www
DocumentRoot:HTML文件的根目錄(也就是網站的目錄)。

(5)ServerName的設置

修改#ServerName www.your.org.here
為 ServerName www.your.org.here
否則會出現錯誤“gethostbyname::No such file or directory”
ServerName:指定服務器的名稱,當客戶端使用gethostname + gethostbyname時返回給客戶端。

六、補充

后續一口君會在本篇文章基礎之上,繼續講解HTTP協議,並基於該服務器實現一個物聯網綜合項目。

敬請大家關注!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM