• 【ARM】在NUC977上搭建基于boa的嵌入式web服务器


    一、实验目的

    搭建基于arm开发板的web服务端程序,通过网页控制开发板LED状态

    二、boa简介

    Boa服务器是一个小巧高效的web服务器,是一个运行于unix或linux下的,支持CGI的、适合于嵌入式系统的单任务的http服务器,源代码开放、性能高。Boa是一种非常小巧的Web服务器,其可执行代码只有大约60KB左右。作为一种单任务Web服务器,Boa只能依次完成用户的请求,而不会fork出新的进程来处理并发连接请求。但Boa支持CGI,能够为CGI程序fork出一个进程来执行。Boa的设计目标是速度和安全。

    三、源码下载

    下载链接直达:http://www.boa.org/news.html
    在这里插入图片描述

    四、源码编译

    # 解压
    tar- xvf boa-0.94.14rc21.tar.gz
    cd boa-0.94.14rc21
    # 配置生成makefile
    ./configure
    # 修改makefile编译工具:这里选择自己的交叉编译器
    vim ./src/Makefile
    
    CC = arm-linux-gcc
    CPP = arm-linux-gcc -E
    
    # 编译
    make
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述
    为了保险期间我们使用file指令查看一下生成的文件是否为arm版本
    在这里插入图片描述
    然后我们开始准备开发板上需要的文件配置

    mkdir nuc977
    cp src/boa
    cp src/boa ./nuc977/
    cp examples/boa.conf ./nuc977/
    cp /etc/mime.types ./nuc977/
    touch ./nuc977/group
    mkdir ./nuc977/www
    mkdir ./nuc977/www/cgi-bin
    touch ./nuc977/index.html
    cd nuc977/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    // 如果这里没有example文件夹可以使用“find ./ -name boa.conf”这个命令查找一下源码下conf文件的位置一定有的
    在这里插入图片描述
    然后将这些文件传输到nfs文件夹中

    五、开发板配置

    mkdir /etc/boa
    cp /mnt/nuc977/www / -rf
    cp /mnt/nuc977/boa /etc/boa
    cp /mnt/nuc977/boa.conf /etc/boa
    cp /mnt/nuc977/mime.types /etc
    cp /mnt/nuc977/group /etc
    cp /mnt/nuc977/index.html /www
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后需要修改我们的etc/boa/box.conf文件内容

    Group nogroup 改为Group 0 // 修改nogroup为0
    ErrorLog /etc/boa/error_log  // 更改路径
    AccessLog /etc/boa/access_log // 更改路径
    ServerName www.your.org.here // 取消注释
    DocumentRoot /www  // 修改路径
    ScriptAlias /cgi-bin/ /www/cgi-bin/  // 修改路径
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    修改index.html界面,内容如下:

     <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>LED控制页面</title>
        </head>
        <body> 
    		<input type="button" value="开"/>
    		<input type="button" value="关"/>
        </body>
    </html> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    cd /etc/boa 
     ./boa
    
    • 1
    • 2

    然后我们ifconfig查看开发板ip,然后在我们pc端浏览器输入该ip地址查看效果
    在这里插入图片描述

    六、控制led灯实验

    方案1

    boaapp.c文件

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <stdint.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    void led_on()
    {
        char ubuf[2] = {1, 0};    
        int fd; 
    
        fd = open("/dev/led",O_RDWR);
     
        if(fd < 0)
        {
            printf("open runled device error\r\n");
            return;
        }   
        write(fd, ubuf, 1); 
        close(fd);
    }
    
    void led_off()
    {
        char ubuf[2] = {0, 0};    
        int fd; 
    
        fd = open("/dev/led",O_RDWR);
     
        if(fd < 0)
        {   
            printf("open runled device error\r\n");
            return;
        }   
        write(fd, ubuf, 1); 
        close(fd);
    }
    
    int main(void)
    {
        char *data;
    
        printf("Content-Type:text/html;charset=gb2312\n\n");//它是一个MIME头信息,它告诉Web服务器随后的输出是以html的形式
        printf("<html>\n");
        printf("<body>\n");
        printf("<title>this is title</title> ");
        printf("<h3>this is h3</h3> ");
        data = getenv("QUERY_STRING");//得到客户端发送过来的数据
        printf("<p>接受到的数据为:%d</p>",data);
        if(strcmp(data,"on"))
        {
            led_on();
        }else if(strcmp(data,"off"))
        {
            led_off();
        }
        printf("</body>\n");
        printf("</html>\n");
    
        // free(data);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    编译

    arm-linux-gcc boaapp.c -o boaapp.cgi -static
    
    • 1

    然后我们将编译出来的文件拷贝到开发板的www/cgi-bin文件夹中,然后我们进入浏览器进行访问,然后一直出现错误,经过实验可以得知问题出在函数getenv上(http://192.168.1.3/cgi-bin/boaapp.cgi)
    在这里插入图片描述
    在这里插入图片描述
    只要把这里注释掉就正常访问了
    在这里插入图片描述

    方案2

    下载https://github.com/boutell/cgic
    修改cgictest.c

    #include"cgic.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <stdint.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    void led_on()
    {
        char ubuf[2] = {1, 0};     
        int fd;
    
        fd = open("/dev/led",O_RDWR);
     
        if(fd < 0)
        {
            printf("<p align=\"center\">open onled device error<\p>>");
            return;
        }
        write(fd, ubuf, 1);
        close(fd);
    }
    
    void led_off()
    {
        char ubuf[2] = {0, 0};     
        int fd;
    
        fd = open("/dev/led",O_RDWR);
     
        if(fd < 0)
        {
            printf("<p align=\"center\">open offled device error<\p>>");
            return;
        }
        write(fd, ubuf, 1);
        close(fd);
    }
    int cgiMain()
    { 
    	char state[10]; 
    	// cgiFormString("led_num", led_num, 10); // 从表单中的led_num字段获取值存入到led_num 
    	cgiFormString("state", state, 10);// 从表单中的led_state字段获取值存入到led_state 
    	cgiHeaderContentType("text/html"); // 设定输出的内容格式 这里我们要输出HTML
    	fprintf(cgiOut,"<title>LED Test</title>"); 
    	fprintf(cgiOut,"<p align=\"center\">recv from arm:</p>");
    	fprintf(cgiOut,"<form action=\"cgictest.cgi\" align=\"center\">LED_STATE<br><input type=\"text\" name=\"state\" \
    					value=\"on\"><br><input type=\"submit\" value=\"push\"></form>");
    	// fprintf(cgiOut,"led_num: %s", led_num);
    	fprintf(cgiOut,"<br> <p align=\"center\">state: %s</p>", state);
    	
    	if(!strcmp(state,"on"))
        {
            led_on();
    		system("echo 1>/dev/led");
        }else if(!strcmp(state,"off"))
        {
            led_off();
    		system("echo 0>/dev/led");
        }
    	
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    修改makefile:参考

    CFLAGS=-g -Wall
    CC=arm-linux-gcc
    AR=arm-linux-ar
    RANLIB=arm-linux-ranlib
    LIBS=-L./ -lcgic
    
    all: libcgic.a cgictest.cgi
    
    install: libcgic.a
    	cp libcgic.a /usr/local/lib
    	cp cgic.h /usr/local/include
    	@echo libcgic.a is in /usr/local/lib. cgic.h is in /usr/local/include.
    
    libcgic.a: cgic.o cgic.h
    	rm -f libcgic.a
    	$(AR) rc libcgic.a cgic.o
    	$(RANLIB) libcgic.a
    
    #mingw32 and cygwin users: replace .cgi with .exe
    
    cgictest.cgi: cgictest.o libcgic.a
    	$(CC) cgictest.o -o cgictest.cgi ${LIBS}
    
    clean:
    	rm -f *.o *.a cgictest.cgi capture cgicunittest
    
    test:
    	$(CC) -D UNIT_TEST=1 cgic.c -o cgicunittest
    	./cgicunittest
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    最后目录组成
    在这里插入图片描述
    执行make然后将生成的.cgi文件拷贝到板子的www/cgi-bin目录下然后打开浏览器
    最终效果(目前)
    在这里插入图片描述

  • 相关阅读:
    PlayWright(十二)- PO模式
    VirtualBox网络配置
    2023年最新版Apollo保姆级使用手册(超级详尽版本)
    供应链管理——企业之间的进程与联络
    深拷贝和浅拷贝的主要区别
    基于python的PDF文件解析器汇总
    Qt学习11 Qt 中的字符串类
    【论文精读】Evaluating Large Language Models Trained on Code
    深入理解 Spring Boot 内置工具类:ReflectionUtils
    Docker安装mysql实战说明
  • 原文地址:https://blog.csdn.net/qq_43581670/article/details/125337013