嵌入式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碼雲

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章