嵌入式linux项目开发(一)——web数据交互

2019-07-12 16:50发布

http://blog.csdn.net/a642960662/article/details/66473799

嵌入式linux项目开发(一)——web数据交互

    本文讲解如何在移植好BOACGICSQLite嵌入式web服务器上通过数据交互web网页配置个人信息,由CGI程序将配置的信息保存到SQLite数据库

一、嵌入式web服务器工作原理

    服务器软件(BOA)始终在HTTP 端口守候客户的连接请求,当客户向服务器发起一个连接请求后,客户和服务器之间经过“三步握手”建立起连接。在接收到客户端的HTTP 请求消息后,服务器对消息进行解析,包括:读取请求URL、映射到对应的物理文件、区分客户端请求的资源是静态页面还是CGI 应用程序等。如果客户请求的是静态文件,那么服务器读取相应的磁盘文件,并将其作为HTTP响应消息中的实体返回给客户端,如果客户端请求的是CGI 应用程序,那么服务器将创建相应的CGI 应用程序进程,并将各种所需信息(客户端请求信息、服务器端相关信息等)按CGI 规范传递给CGI 应用程序进程,此后由CGI 应用程序接管控制。         CGI应用程序读取从Web 服务器传递来的各种信息,并对客户端的请求进行解释和处理,如使用SQL 语句来检索或者更新数据库,或者将从客户端获得的数据,按与被监控对象所定义的通信协议重新组帧,从UART 口发送到被监控对象。最后CGI 应用程序会将处理结果按照CGI 规范返回给Web 服务器,Web 服务器会对CGI 应用程序的处理结果进行解析,并在此基础上生成HTTP 响应信息返回给客户端。     嵌入式web服务器所要实现的功能是让客户端使用浏览器向服务器发送 HTTP请求,服务器响应客户端的请求后,并引导到指定的脚本程序,对命令进行解析,将信息交给后台——CGI去处理。CGI解析信息后,向远程设备发出控制信息。设备响应后,返回给CGI控制信息,CGI再将信息解析成变量输出到Web Server上,最后客户端得到WebServer发回的页面消息(HTML),就能得到现场设备的运行状态,实现对现场设备的远程监控。     BOA 服务器的的主要功能如下图所示: wKioL1eWtqeCJZZ1AAIzW1lJZSA067.png
    服务器中主要包括BoaCGI两部分,其中Boa管理着返回客户端的WEB页面,而CGI控制着客户端和服务器端的信息交换,所以我们可以通过编写相应的CGI程序来实现所需要的功能。Boa服务器的实现主要分为两步,boa服务器的移植和CGI程序的设计。         CGI的程序编写包括两个部分:HTML代码和C代码;CGI程序与Boa Web服务器之间通过环境变量、命令行参数和标准输入等方式进行通信。一般采用表单编码信息通过环境变量QUERY_STRING传递。在编写CGI程序时,需要注意     A、REQUEST_METHOD     请求方法有两种:GETPOST
    B、环境变量     在选用不同的方法时,所对应的环境变量也不同。选择GET时,所对应的环境变量是QUERY_STRING,通过调用库函数getenv()来得到环境变量的具体值,即querystring=getenv(QUERY_STRING)。系统功能框架图如下: wKiom1eWts2zRnThAAD-P4GtkgA709.png         本文主要使用表单实现个人信息的提交,通过CGI程序处理将信息数据存储到SQLite数据库,其余摄像头信息采集和GPRS模块由于没有相关硬件设备,不在本文实现。

二、HTML数据交互网页设计

wKioL1eWturhZeUyAAAmMX16wqU975.png
Config.html: [html] view plain copy
  1. ><head><meta http-equiv="Content-Type" content="text/html "><title>系统参数配置title>head> <body><h3>配置选项h3> <form enctype="multipart/form-data" action="cgi-bin/config.cgi" method="post">    <fieldset style='width:300px' >    <table>    <legend>个人信息legend>        <tr>            <td><label for="name">姓名:label>td>            <td><input type="text" id="name" name="name" />td>        tr>        <tr>            <td><label for="age">年龄:label>td>            <td><input type="text" id="age" name="age" />td>        tr>        <tr>            <td><label for="sex">性别:label>td>            <td><input type="radio" name='sex' value='boy' />男 <input type="radio" name='sex' value='girl'/>td>        tr>        <tr>            <td><label for="company">单位:label>td>            <td><input type="text" id="company" name="company" />td>        tr>        <tr>            <td><label for="profession">职业:label>td>            <td><input type="text" id="profession" name="profession" />td>        tr>        <tr>            <td><label for="idnumber">身份证号码:label>td>            <td><input type="text" id="idnumber" name="idnumber" />td>        tr>        <tr>            <td><label for="qq">QQ码:label>td>            <td><input type="text" id="qq" name="QQ" />td>        tr>        <tr>            <td><label for="email">Email:label>td>            <td><input type="text" id="email" name="email" />td>        tr>        <tr>            <td><label for="telephone">联系电话:label>td>            <td><input type="text" id="telephone" name="telephone" />td>        tr>        <tr>            <td>            <center>                <input type="submit" id="ok" name="ok" value="确定"/>td>            center>            td>        tr>    table>    fieldset>    <br>form>  body>  

三、CGI程序设计

    将接收的配置信息返回给客户端浏览器,同时将配置信息写入SQLite数据库。 config.c源码: [cpp] view plain copy
  1. #include    #include    #include    #include    #include    #include #include "cgic.h" #include "sqlite3.h" #define SQL_SIZE 256 int cgiMain(int argc, char **argv){char name[64];char age[4];char sex[8];char company[64];char profession[16];char idnumber[24];char qq[24];char email[64];char telephone[16];//回显信息到HTML网页cgiHeaderContentType("text/html"); printf(" ");printf("

    ");//获取表单中的name的值,存入name缓冲区if(cgiFormString("name", name, sizeof(name)) != cgiFormSuccess){fprintf(stderr, "cgiFormString function name failed");exit(-1);}printf("姓名:%s ",name);printf("
    ");if(cgiFormString("age", age, sizeof(age)) != cgiFormSuccess){fprintf(stderr, "cgiFormString function age failed");exit(-1);}printf("年龄:%s ",age);printf("
    ");if(cgiFormString("sex", sex, sizeof(sex)) != cgiFormSuccess){fprintf(stderr, "cgiFormString function sex failed");exit(-1);}printf("性别:%s ",sex);printf("
    ");if(cgiFormString("company", company, sizeof(company)) != cgiFormSuccess){fprintf(stderr, "cgiFormString function company failed");exit(-1);}printf("单位:%s ",company);printf("
    ");if(cgiFormString("profession", profession, sizeof(profession)) != cgiFormSuccess){fprintf(stderr, "cgiFormString function profession failed");exit(-1);}printf("职业:%s ",profession);printf("
    ");if(cgiFormString("idnumber", idnumber, sizeof(idnumber)) != cgiFormSuccess){fprintf(stderr, "cgiFormString function idnumber failed");exit(-1);}printf("身份证号码:%s ",idnumber);printf("
    ");if(cgiFormString("email", email, sizeof(email)) != cgiFormSuccess){fprintf(stderr, "cgiFormString function email failed");exit(-1);}printf("Email:%s ",email);printf("
    ");if(cgiFormString("telephone", telephone, sizeof(telephone)) != cgiFormSuccess){fprintf(stderr, "cgiFormString function telephone failed");exit(-1);}printf("Telepone:%s ",telephone);printf("
    ");if(cgiFormString("qq", qq, sizeof(qq)) != cgiFormSuccess){fprintf(stderr, "cgiFormString function qq failed");printf("cgiFormString function qq failed");exit(-1);}printf("QQ号码:%s ",qq);printf("
    ");printf("

    ");printf(" ");//数据存储到数据库sqlite3 *db;int result;result = sqlite3_open("person.db", &db);    if(result != SQLITE_OK)    {        printf("Fail to sqlite3_open person.db: %s. ", sqlite3_errmsg(db));        exit(-1);    }char *errmsg;char sql[SQL_SIZE];bzero(sql, SQL_SIZE);strcpy(sql, "CREATE TABLE person(ID varchar(24) PRIMARY KEY,name text,age text, sex text, company text, profession text, qq text, email text, telephone text);");    if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)    {        printf("Fail to exec sql: %s. ", errmsg);        printf(" %s ",sql);        exit(-1);    }    bzero(sql, SQL_SIZE);strcpy(sql, "INSERT INTO person values('1234567899876543', '天山老妖', '30', 'boy', '天山', '嵌入式工程师', '123455678', 'hello@qq.com', '123344');");if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)    {        printf("Fail to exec sql: %s. ", errmsg);        printf(" %s ",sql);        exit(-1);    }result = sqlite3_close(db);    if(result != 0)    {        fprintf(stderr, "Fail to sqlite3_open person.db : %s. ", sqlite3_errmsg(db));        exit(-1);    }return 0;}
      
    注意:程序需要使用CGIC库的接口函数、SQLite数据库的接口函数,因此编译时需要包括相关文件sqlite3.ccgic.c,同时需要SQLite数据库的动态链接库支持,因此需要将编译后SQLite数据库的lib目录下的文件拷贝到交叉编译工具的lib目录中,编译时需指定-lsqlite3 编译程序:arm-Linux-gcc -o config.cgi config.c  sqlite3.c cgic.c -lsqlite3 将编译后的config.cgi程序拷贝到开发板的www目录下的cgi-bin目录 打开客户端浏览器:http://192.168.6.210/config.html 输入配置信息,提交将会显示配置的内容信息 查看数据库中的内容: sqlite> select * from person; 1234567899876543||30|boy|||123455678|hello@qq.com|123344 sqlite> wKioL1eWtxWhXcdDAAAzmRqGxSE301.png
    至此,在BOA搭建的嵌入式WEB服务器上,使用CGIC处理HTML网页表单提交的信息,存储到SQLite数据库的简单项目已经完成。本项目只是简单的介绍的整个过程,是一个入门级的项目。如果有实际项目需求需要更精细的学习相关知识。
本文出自 “生命不息,奋斗不止” 博客,转载请与作者联系!
0
0