嵌入式web服务器BOA+CGI+HTML+MySQL项目实战——Linux


准备环境

操作系统: Ubuntu12.04 LTS
环境搭建: 需要 BOA,Apache,CCGI,MySQL,GCC
Linux下嵌入式Web服务器BOA和CGI编程开发
数据库的相关知识——学习笔记 的三
mysql中文乱码问题解决 / C程序插入仍是乱码解决 / 卸载重装教学
扩展: 我还用了bootstrap框架,CSS/JS
源码链接:GitHub:传送门 , 码云:传送门

使用方法

环境准备好后,我们在 /var/www 下写HTML文件

在 /var/www/cgi-bin 下写c文件,编译后命名为.cgi。
编译命令仅供参考
gcc -o login.cgi login.c cgic.c -lpthread -ldl -lmysqlclient

程序都写好后,我们开始测试。

1、开启MySQL服务 默认开启

我的程序需要事先 新建用户test,数据库register,表user

mysql -utest -ptest
// 创建新用户test
mysql> create user 'test'@'localhost' identified by 'test';
// 给test用户所有权限
mysql> grant all privileges on *.*  to test@localhost identified by 'test';
// 刷新权限
mysql> flush privileges;
mysql> create database register;
mysql> use register;
mysql> CREATE TABLE user(username varchar(20) PRIMARY KEY,password varchar(20));

2、开启BOA服务器,在/boa/src目录下 sudo ./boa

3、打开浏览器,访问localhost:端口号 访问的即 /var/www 目录
我直接访问 http://localhost:886/login.html 我的登录页面


其他页面都是同理。

思路讲解


开启boa服务器后,我们访问到我们在 /var/www 下编写的HTML文件,显示我们的登录页面。
我们点击“注册”按钮,跳转到 register.html


点击“注册”按钮,提交form表单信息给cgi-bin/register.cgi

cgi程序通过 cgiFormString函数试图检索发送给指定字段的字符串。存入变量中。我们连接MySQL数据库


将数据写入register数据库中的user表中(此数据库和表需要先建好)

处理完毕后,跳回 login.html 登录页面


现在我们输入数据,点击“登录”,同理将表单发给 login.cgi ,对数据在MySQL数据库中查询后,成功就来到base_config.html 配置页面。

然后我们输入相应数据,点击“提交”,交给base_config.cgi处理,之后任意发挥就好了。

我是打印出来,写入系统文件的代码暂时注释了,慎用

遇到问题可以参考页首的链接


相关源码

login.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>register</title>
<script src="js/jquery-2.2.3.min.js"></script>
<script src="js/jquery-ui.min.js"></script>
<link type="text/css" href="css/jquery-ui.min.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/bootstrap.min.js"></script>
<link type="text/css" href="css/login.css" rel="stylesheet">
<script src="js/my.js"></script>
<SCRIPT language = "JavaScript">
    function checkUserName(){    //验证用户名
        var fname = document.myform.username.value;
        var reg=/^[0-9a-zA-Z]/;
        if(fname.length != 0){
            for(i=0;i<fname.length;i++){
                if(!reg.test(fname)){
                    alert("只能输入字母或数字");
                    return false;}
            }
            if(fname.length<4||fname.length>16){
                alert("只能输入4-16个字符")
                return false;
            }
        }
        else{    alert("请输入用户名");
            document.myform.username.focus();
            return false     }
        return true;
    }

    function passCheck(){ //验证密码
        var userpass = document.myform.password.value;
        if(userpass == ""){
            alert("未输入密码 \n" + "请输入密码");
            document.myform.password.focus();
            return false;   }
        if(userpass.length < 6||userpass.length>12){
            alert("密码必须在 6-12 个字符。\n");
            return false;   }
        return true;   }

    function passCheck2(){
        var p1=document.myform.password.value;
        var p2=document.myform.password2.value;
        if(p1!=p2){
            alert("确认密码与密码输入不一致");
            return false;
        }else{
            return true;
        }
    }

    function checkEmail(){
        var Email = document.getElementById("email").value;
        var e = Email.indexOf("@"&&".");
        if(Email.length!=0){
            if(e>0){
                if(Email.charAt(0)=="@"&&"."){
                    alert("符号@和符号.不能再邮件地址第一位");
                return false;
                }
                else{
                    return true;
                }
            }
            else{
                alert("电子邮件格式不正确\n"+"必须包含@符号和.符号!");
                return false;
            }
        }
        else{
            alert("请输入电子邮件!")
            return false;
        }
    }

    function checkbirthday(){    //验证用户名
        var year = document.myform.birthday.value;
        if(year < 1949 || year > 2007){
            alert("年份范围从1949-2007年");
            return false;}
        return true;     }


    function validateform(){
        if(checkUserName()&&passCheck( )&&passCheck2()&&checkEmail()&&checkbirthday())
                return true;
        else
            return false;
    }

    function clearText( ) {
        document.myform.user.value="" ;
        document.myform.password.value="" ;
    }

    //显示隐藏对应的switchPwd()方法:
    $(function(){
        // 通过jqurey修改
        $("#passwordeye").click(function(){
            let type =  $("#password").attr('type')
            if(type === "password"){
                $("#password").attr("type","text");
            }else{
                $("#password").attr("type","password");
            }
        });
    });


</SCRIPT>
</head>
<body>
<img src="img/login_bg.jpg" class="bg">
<div id="head">
    <img src="img/login_head.png" width=100% height=auto />
</div>
<div id="center">
<form name="myform" onSubmit="return validateform( )" enctype="multipart/form-data" action="cgi-bin/login.cgi" method="post" >
    <div class="input-group">
        <h3>用户名:</h3>&nbsp;<input class="form-control" id="username" name="username" type="text"  style="height:40px" value="" placeholder="只能输入字母或数字,4-16个字符"/>
    </div>
    <div class="input-group">        
        <h3>&nbsp;&nbsp;&nbsp;码:</h3>&nbsp;<input class="form-control" id="password" name="password" type="password" style="height:40px"  value="" placeholder="密码长度6-12位"/>
        <span class="input-group-btn">
            <INPUT class="btn btn-default" id="passwordeye" type="button" value="show/hide"">
        </span>
    </div>

    <div id="btn">
        <INPUT class="btn btn-primary" name="loginButton" type="submit" id="Button" value="登录"  onclick="checkUserName()">
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        <a href="register.html"><INPUT class="btn btn-primary" name="registerButton" id="Button" type="button" value="注册"></a>
    </div>
</form>
</div>
<div id="bottom">
    <div class="footer" style="color:white;">
         Copyright &copy; 2013-2019 All Rights Reserved. 备案号:
    </div>
</div>
</body>
</html>

对应 login.c

#include <stdio.h>
#include "cgic.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <mysql/mysql.h>
#include <stdbool.h>

#define SQL_SIZE 256 

int cgiMain(void)
{
    char username[20];
    char password[20];
    char email[40];
    //回显信息到HTML网页cgiHeaderContentType("text/html");
    printf("<html>\n\n");
    printf("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\n");
    printf("<p>\n\n");

    if(cgiFormString("username", username, sizeof(username)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function username failed");
        //exit(-1);
    }
    printf("用户名:%s\n\n",username);
    printf("<br>\n\n");
    // password gateway server_ip dns subnet_mask dhcp error
    if(cgiFormString("password", password, sizeof(password)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function password failed");
        //exit(-1);
    }
    printf("密码:%s\n\n",password);
    printf("<br>\n\n");
/*
    if(cgiFormString("email", email, sizeof(email)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function email failed");
        //exit(-1);
    }
    printf("电子邮箱:%s\n\n",phone);
    printf("<br>\n\n");
*/

    /***  将用户信息写入MySQL数据库中  ***/ 
    //数据存储到数据库
    MYSQL* conn;
    bool isAutoCommit;

    // 初始化 MySQL
    conn = mysql_init(NULL);
    if(NULL == conn)
    {
        printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
        exit(-1);
    }

    char ip[16] = "127.0.0.1";
    char user[20] = "test";
    char passwd[20] = "test";
    char database[20] = "register";
    int port = 3306;

    // 尝试与运行在主机上的MySQL数据库引擎建立连接
    if(NULL == mysql_real_connect(conn,ip,user,passwd,database,port,NULL,0))
    {
        printf("---errno:%d error:%s\n\n",mysql_errno(conn),mysql_error(conn));
        exit(-1);
    }

    isAutoCommit = true;
    // 根据mysql的autocommit参数设置来决定是否自动提交
    mysql_autocommit(conn,isAutoCommit);

    // 设定数据库编码
    mysql_query(conn,"SET NAMES 'utf8'");
    mysql_query(conn,"SET CHARACTER SET utf8");
    mysql_query(conn,"SET CHARACTER_SET_RESULT = utf8");

    char cmd[SQL_SIZE];
    // 置字节字符串cmd的前SQL_SIZE个字节为零且包括‘\0’
    bzero(cmd, SQL_SIZE);
    // 创建user表
    // strcpy(cmd, "CREATE TABLE user(username varchar(20) PRIMARY KEY,password varchar(20));");

    // 将sql语句写入cmd变量
    sprintf(cmd, "select * from user where username='%s' and password='%s';",username,password);

    MYSQL_RES *res;
    MYSQL_ROW row;

    // 向与指定的连接标识符关联的服务器中的当前活动数据库发送一条查询
    if(mysql_query(conn,cmd) != 0)
    {
        printf("errno:%d error:%s\n\n",mysql_errno(conn),mysql_error(conn));
        exit(-1);
    }

    int num_fields = mysql_field_count(conn);
    if(num_fields == 0)
    {
        printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
        return -1;    
    }

    res = mysql_store_result(conn);
    if(NULL == res)
    {
        printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
        return -1;
    }

    printf("<br>\n\n");
    printf("<br>\n\n");
    int count = 0;
    while((row = mysql_fetch_row(res)))
    {
        char arr[1000];
        int i = 0;
        for( ; i<num_fields; i++)
        {
            printf("%s ",row[i]);
        }
        printf("\n\n");
        printf("<br>\n\n");
        count++;
    }    
    mysql_free_result(res);

    if(count != 0)
    {
        printf("<p>登陆成功</p>\n\n");
        sleep(1);
        printf("<meta http-equiv=Refresh content=1;URL=../base_config.html>\n"); 
    }
    else
    {
        printf("<p>帐号或密码错误</p>\n\n");
        sleep(1);
        printf("<meta http-equiv=Refresh content=1;URL=../login.html>\n"); 
    }

    //printf("<p></p>\n\n");

    return 0;
}

register.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>register</title>
<script src="js/jquery-2.2.3.min.js"></script>
<script src="js/jquery-ui.min.js"></script>
<link type="text/css" href="css/jquery-ui.min.css" rel="stylesheet">
<link type="text/css" href="css/register.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/bootstrap.min.js"></script>
<script src="js/my.js"></script>
<SCRIPT language = "JavaScript">
    function checkUserName(){    //验证用户名
        var fname = document.myform.username.value;
        var reg=/^[0-9a-zA-Z]/;
        if(fname.length != 0){
            for(i=0;i<fname.length;i++){
                if(!reg.test(fname)){
                    alert("只能输入字母或数字");
                    return false;}
            }
            if(fname.length<4||fname.length>16){
                alert("只能输入4-16个字符")
                return false;
            }
        }
        else{    alert("请输入用户名");
            document.myform.username.focus();
            return false     }
        return true;
    }

    function passCheck(){ //验证密码
        var userpass = document.myform.password.value;
        if(userpass == ""){
            alert("未输入密码 \n" + "请输入密码");
            document.myform.password.focus();
            return false;   }
        if(userpass.length < 6||userpass.length>12){
            alert("密码必须在 6-12 个字符。\n");
            return false;   }
        return true;   }

    function passCheck2(){
        var p1=document.myform.password.value;
        var p2=document.myform.password2.value;
        if(p1!=p2){
            alert("确认密码与密码输入不一致");
            return false;
        }else{
            return true;
        }
    }

    function checkEmail(){
        var Email = document.getElementById("email").value;
        var e = Email.indexOf("@"&&".");
        if(Email.length!=0){
            if(e>0){
                if(Email.charAt(0)=="@"&&"."){
                    alert("符号@和符号.不能再邮件地址第一位");
                return false;
                }
                else{
                    return true;
                }
            }
            else{
                alert("电子邮件格式不正确\n"+"必须包含@符号和.符号!");
                return false;
            }
        }
        else{
            alert("请输入电子邮件!")
            return false;
        }
    }

    function checkbirthday(){    //验证用户名
        var year = document.myform.birthday.value;
        if(year < 1949 || year > 2007){
            alert("年份范围从1949-2007年");
            return false;}
        return true;     }


    function validateform(){
        if(checkUserName()&&passCheck( )&&passCheck2()&&checkEmail()&&checkbirthday())
                return true;
        else
            return false;
    }

    function clearText( ) {
        document.myform.user.value="" ;
        document.myform.password.value="" ;
    }

    //显示隐藏对应的switchPwd()方法:
    $(function(){
        // 通过jqurey修改
        $("#passwordeye").click(function(){
            let type =  $("#password").attr('type')
            if(type === "password"){
                $("#password").attr("type","text");
            }else{
                $("#password").attr("type","password");
            }
        });
        $("#passwordeye2").click(function(){
            let type =  $("#password2").attr('type')
            if(type === "password"){
                $("#password2").attr("type","text");
            }else{
                $("#password2").attr("type","password");
            }
        });
    });

</SCRIPT>
</head>
<body>
<img src="img/login_bg.jpg" class="bg">
<div id="head">
    <img src="img/register_head.png" width=100% height=auto />
</div>
<div id="center">
<form name="myform" onSubmit="return validateform( )" enctype="multipart/form-data" action="cgi-bin/register.cgi" method="post" >
    <div class="input-group">
        <h3>&nbsp;&nbsp;&nbsp;&nbsp;名:</h3><input class="form-control"  id="username" name="username" type="text"  style="height:40px" value=""  placeholder="只能输入字母或数字,4-16个字符"/>
    </div>        
    <div class="input-group">
        <h3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;码:</h3><input class="form-control"  id="password" name="password" type="password" style="height:40px" value=""  placeholder="密码长度6-12位"/>
        <span class="input-group-btn">
            <INPUT class="btn btn-default" id="passwordeye" type="button" value="show/hide"">
        </span>
    </div>
    <div class="input-group">
        <h3>确认密码:</h3><input class="form-control"  id="password2" name="password2" type="password" style="height:40px" value=""/>
        <span class="input-group-btn">
            <INPUT class="btn btn-default" id="passwordeye2" type="button" value="show/hide"">
        </span>
    </div>     
    <div id="btn">
        <INPUT name="registerButton"  class="btn btn-primary" type="submit" id="Button" value="注册"  onclick="checkUserName()">
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    
        <a href="login.html"><INPUT  class="btn btn-primary" name="loginButton" id="Button" type="button" value="登录"></a>
    </div>
</form>
</div>
<div id="bottom">
    <div class="footer" style="color:white;">
         Copyright &copy; 2013-2019 All Rights Reserved. 备案号:
    </div>
</div>
</body>
</html>

对应的 register.c

#include <stdio.h>
#include "cgic.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <mysql/mysql.h>
#include <stdbool.h>

#define SQL_SIZE 256 

int cgiMain(void)
{
    char username[20];
    char password[20];
    char email[40];
    //回显信息到HTML网页cgiHeaderContentType("text/html");
    printf("<html>\n\n");
    printf("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\n");
    printf("<p>\n\n");

    if(cgiFormString("username", username, sizeof(username)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function username failed");
        //exit(-1);
    }
    printf("用户名:%s\n\n",username);
    printf("<br>\n\n");
    // password gateway server_ip dns subnet_mask dhcp error
    if(cgiFormString("password", password, sizeof(password)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function password failed");
        //exit(-1);
    }
    printf("密码:%s\n\n",password);
    printf("<br>\n\n");
/*
    if(cgiFormString("email", email, sizeof(email)) != cgiFormSuccess)
    {
        fprintf(stderr, "cgiFormString function email failed");
        //exit(-1);
    }
    printf("电子邮箱:%s\n\n",phone);
    printf("<br>\n\n");
*/

    /***  将用户信息写入MySQL数据库中  ***/ 
    //数据存储到数据库
    MYSQL* conn;
    bool isAutoCommit;

    // 初始化 MySQL
    conn = mysql_init(NULL);
    if(NULL == conn)
    {
        printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
        exit(-1);
    }

    char ip[16] = "127.0.0.1";
    char user[20] = "test";
    char passwd[20] = "test";
    char database[20] = "register";
    int port = 3306;

    // 尝试与运行在主机上的MySQL数据库引擎建立连接
    if(NULL == mysql_real_connect(conn,ip,user,passwd,database,port,NULL,0))
    {
        printf("---errno:%d error:%s\n\n",mysql_errno(conn),mysql_error(conn));
        exit(-1);
    }

    isAutoCommit = true;
    // 根据mysql的autocommit参数设置来决定是否自动提交
    mysql_autocommit(conn,isAutoCommit);

    // 设定数据库编码
    mysql_query(conn,"SET NAMES 'utf8'");
    mysql_query(conn,"SET CHARACTER SET utf8");
    mysql_query(conn,"SET CHARACTER_SET_RESULT = utf8");

    char cmd[SQL_SIZE];
    // 置字节字符串cmd的前SQL_SIZE个字节为零且包括‘\0’
    bzero(cmd, SQL_SIZE);
    // 创建user表
    // strcpy(cmd, "CREATE TABLE user(username varchar(20) PRIMARY KEY,password varchar(20));");

    // 将sql语句写入cmd变量
    sprintf(cmd, "INSERT INTO user values('%s', '%s');",username,password);

    printf("%s\n\n",cmd);

    // 向与指定的连接标识符关联的服务器中的当前活动数据库发送一条查询
    if(mysql_query(conn,cmd) != 0)
    {
        printf("errno:%d error:%s\n\n",mysql_errno(conn),mysql_error(conn));
        printf("<p>注册失败,请重新注册</p>\n\n");    
        sleep(1);
        printf("<meta http-equiv=Refresh content=1;URL=../register.html>\n");       
    }
    //mysql_affected_rows(conn);

    printf("<p>注册成功</p>\n\n");    
    printf("<br>\n\n");
    printf("<p>您的用户名和密码为:</p>\n\n");    

    sprintf(cmd,"select * from user;");

    MYSQL_RES *res;
    MYSQL_ROW row;

    if(mysql_query(conn,cmd) != 0)
    {
        printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
        return -1;
    }

    int num_fields = mysql_field_count(conn);
    if(num_fields == 0)
    {
        printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
        return -1;    
    }

    res = mysql_store_result(conn);
    if(NULL == res)
    {
        printf("errno:%d error:%s\n",mysql_errno(conn),mysql_error(conn));
        return -1;
    }

    printf("<br>\n\n");
    printf("<br>\n\n");
    while((row = mysql_fetch_row(res)))
    {
        char arr[1000];
        int i = 0;
        for( ; i<num_fields; i++)
        {
            printf("%s ",row[i]);
        }
        printf("\n\n");
        printf("<br>\n\n");
    }

    mysql_free_result(res);

    sleep(1);

    printf("<meta http-equiv=Refresh content=1;URL=../login.html>\n");   

    return 0;
}

其余参考GitHub码云


Author: Ikaros
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Ikaros !
评论
 Previous
B站动态转发抽奖脚本+教程 B站动态转发抽奖脚本+教程
运行python脚本需要的条件:1、连通的网络2、已安装Python2并配置环境变量3、Python脚本源码 环境搭建:网络就不用我说了(〃’▽’〃) 那么下面我们来安装python吧。Python官网有2个版本2和3,我们选择2,因为语
2019-11-08
Next 
ARM体系结构——九鼎创展x210V3s ARM体系结构——九鼎创展x210V3s
ARM体系结构-在裸板下的开发、单片机Linux系统移植-给开发板安装操作系统Linux系统驱动编程-对内核进行扩展 开发板 SD卡 电源线 网线 串口线 蓝色USB线 一、嵌入式介绍1、什么是嵌入式系统
2019-10-27
  TOC