Linux_网络项目_WEB服务器结项 设计CGI业务(表单提交注册用户并保存数据库功能测试,解决构建静态库/usr/bin/ld: cannot find -lstdc++报错,项目总结)

文章介绍了如何在C++CGI程序中使用MySQL,处理中文URI编码,以及解决`/usr/bin/ld:cannotfind-lstdc++`报错。同时讨论了项目中涉及的技术点,如连接池、环境变量管理和HTTP长连接等。
摘要由CSDN通过智能技术生成

1.引入MySQL

首先:此HTTP服务器使用线程池处理链接,每个线程如果使用cgi的话,使用进程替换,替换cgi程序。所以CGI程序支持任何后端语言eg:C/C++,Python(编写好后chomd +x 添加可执行权限即可),Java,shell等

这里为了简单,补充使用C设计数据库链接的业务测试.

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
下载完毕,将第三方库引入项目中 rz -e

tar xzf mysql-connector-c-6.1.11-linux-glibc2.12-x86_64.tar.gz

其中需要使用的是include 文件夹和lib文件夹,其他的都不需要可以删掉

将这两个文件夹拷贝到cgi目录下
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
输入下列代码测试数据库导入是否正确

#include <iostream>
#include "./include/mysql.h"
using namespace std;
int main(int argc, char const *argv[])
{
    cout << mysql_get_client_info() << endl;
    return 0;
}

在当前文件夹输入g++ -o test connect.cpp -I include -L lib -lmysqlclient进行编译测试
Linux Centos下载C静态库命令
sudo yum install -y glibc-static
Linux_动态库与静态库回忆

将动态库路径添加到环境变量上
export LD_LIBRARY_PATH=./lib/
LD_LIBRARY_PATH表示程序在运行时动态查找的路径,这样生成的可执行程序可以运行了
在这里插入图片描述

打包静态库 g++ -o connect connect.cpp -I include -L lib -lmysqlclient -lpthread -ldl -static 如果出现

在这里插入图片描述

解决/usr/bin/ld: cannot find -lstdc++报错

原因,没有libstdc++静态库,安装即可
locate libstdc++查找库
在这里插入图片描述
发现无静态库

yum search libstdc++ 查找库
在这里插入图片描述

下载红框的静态库即可 yum install libstdc+±static.x86_64

参考文章

重新运行
g++ -o connect connect.cpp -I include -L lib -lmysqlclient -lpthread -ldl -static 发现生成完毕(忽视警告即可)
在这里插入图片描述

2. CGI链接数据库

服务器对浏览器uri中文加码的解码函数

// 浏览器传参时,中文字符会被编码为 UTF-8 格式,因此服务器需要对 uri 进行 decode 解码。
//  这个函数会对 uri 进行 decode 解码
std::string decode_uri(const std::string &uri)
{
    std::string result; // 用于保存解码后的 uri
    // 遍历 uri 中的每个字符
    for (size_t i = 0; i < uri.size(); i++)
    {
        if (uri[i] == '%')
        { // 如果当前字符是 '%'
            // 如果当前字符后面还有两个字符,则将这两个字符转换为十进制数
            if (i + 2 < uri.size())
            {
                int value = 0;
                std::istringstream iss(uri.substr(i + 1, 2));
                iss >> std::hex >> value;
                // 将转换后的十进制数转换为对应的字符,并添加到结果中
                result += static_cast<char>(value);
                i += 2;
            }
            else
            { // 如果当前字符后面没有两个字符,则将当前字符添加到结果中
                result += uri[i];
            }
        }
        else
        {                     // 如果当前字符不是 '%'
            result += uri[i]; // 直接将当前字符添加到结果中
        }
    }
    return result; // 返回解码后的 uri
}

在这里插入图片描述
在这里插入图片描述

链接数据库CGI

#include <iostream>
#include "./include/mysql.h"
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include "../tool/Util.hpp"
#include <sstream>
using namespace std;
bool GetParameter(string &parameter)
{
    // cout被重定向了,不能使用其打印
    // cerr << "DEBUG CGI:" << getenv("METHOD") << endl;
    std::string method = getenv("METHOD");
    cerr << "DEBUG: CGI get method " << method << endl;
    bool flag = true;
    if ("GET" == method)
    {
        parameter = getenv("Get_Parameter");
        // cerr << "DEBUG CGI GET Parameter:" << parameter << endl;
    }
    else if ("POST" == method)
    {
        // cerr << "DEBUG: CGI POST Parameter" << endl;
        int content_length = atoi(getenv("Content_Length"));
        // cerr << "DEBUG: Countent-Length: " << content_length << endl;
        char ch = 0;
        while (content_length > 0) // 从管道文件中写入
        {
            read(0, &ch, 1);
            parameter += ch;
            content_length -= 1;
        }
        cerr << "DEBUG: POST CGI end msg= " << parameter << endl;
    }
    else
    {
        // TODO 其余方法不处理,默认处理为错误
        flag = false;
    }
    return flag;
}
bool insert(std::string &sql)
{
    MYSQL *connect = mysql_init(nullptr);
    mysql_set_character_set(connect, "utf8"); // 设置编码格式,防止乱码
    // mysql connect+ ip + user name + password + database name + port +null+0
    if (mysql_real_connect(connect, "127.0.0.1", "dodamce", "000000", "HttpSever", 3306, nullptr, 0) == nullptr)
    {
        cerr << "DEBUG error connecting!:" << mysql_error(connect) << endl;
        return false;
    }
    cerr << "DEBUG succeed connecting" << endl;
    int ret = mysql_query(connect, sql.c_str());
    if (ret != 0)
    {
        cerr << "DEBUG error query!:" << mysql_error(connect) << endl;
        return false;
    }
    cerr << "DEBUG succeed query" << endl;
    mysql_close(connect);
    return true;
}
// 浏览器传参时,中文字符会被编码为 UTF-8 格式,因此服务器需要对 uri 进行 decode 解码。
//  这个函数会对 uri 进行 decode 解码
std::string decode_uri(const std::string &uri)
{
    std::string result; // 用于保存解码后的 uri
    // 遍历 uri 中的每个字符
    for (size_t i = 0; i < uri.size(); i++)
    {
        if (uri[i] == '%')
        { // 如果当前字符是 '%'
            // 如果当前字符后面还有两个字符,则将这两个字符转换为十进制数
            if (i + 2 < uri.size())
            {
                int value = 0;
                std::istringstream iss(uri.substr(i + 1, 2));
                iss >> std::hex >> value;
                // 将转换后的十进制数转换为对应的字符,并添加到结果中
                result += static_cast<char>(value);
                i += 2;
            }
            else
            { // 如果当前字符后面没有两个字符,则将当前字符添加到结果中
                result += uri[i];
            }
        }
        else
        {                     // 如果当前字符不是 '%'
            result += uri[i]; // 直接将当前字符添加到结果中
        }
    }
    return result; // 返回解码后的 uri
}
int main(int argc, char const *argv[])
{
    std::string parameter;
    if (GetParameter(parameter))
    {
        // 数据处理 拆分参数
        std::string left;
        std::string right;
        Util::cutString(parameter, "&", left, right);
        std::string key;
        std::string value;
        Util::cutString(left, "=", key, value);
        // 对中文名称进行解码
        key = decode_uri(key);
        value = decode_uri(value);
        // cerr << "DEBUG: " << key << ":" << value << endl;
        std::string key2;
        std::string value2;
        Util::cutString(right, "=", key2, value2);
        // cerr << "DEBUG: " << key2 << ":" << value2 << endl;

        // 插入数据库
        std::string sql = "insert into user (name,passward) values (\'";
        sql += value;
        sql += "\',\'";
        sql += value2;
        sql += "\')";
        cerr << "DEBUG: sql: " << sql << endl;
        if (insert(sql))
        {
            // 返回注册成功网页
            cout << "<html>";
            cout << "<head><meta charset=\"UTF-8\"></head>";
            cout << "<body>";
            cout << "<h1>"
                 << "注册成功"
                 << "</h1>";
            cout << "</body>";
            cout << "</html>";
        }
    }
    return 0;
}

运行截图

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3. 代码位置

Github
Gitee

4. 项目总结

项目完成了HTTP GET,POST方法处理,并且对这两种方法大部分可能出错情况进行处理。模仿Java 的tomcat服务器

搭建了CGI机制:设计创建管道,父子通信,重定向,环境变量导入,数据读写机制,CGI机制支持任何后端语言,Web开发就是开发的CGI程序,常见的CGI程序语言为java和python语言,C++并不适合开发

项目扩展:

  1. 技术方面:

    • 支持HTTP1.1长连接,浏览器可以一直使用这条连接进行通信。涉及连接管理,粘包问题

    • 改成epoll版本HTTP服务器,满足更大量的请求

    • redis进行数据同步

    • 将项目改为请求转发服务器,相当于代理服务器,新增代理服务器功能

  2. 应用功能拓展

    • 在线博客,在线简历,在线画图板,在线视频播放器(HttpSever1.0版本已经支持,网页内嵌视频,需要高配服务器),网络计算器等等
  3. 项目改进点:

    • 可以封装更多数据库方法,删除,更新等操作

    • 支持更多HTTP方法 eg:PUT,DELETE等

    • 宏处理,配置文件化

    • 实现301,302转发功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NUC_Dodamce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值