服务器配置事件
点击确定按钮触发事件:
- 获取控件数据
- 正则判断数据是否合法
- 跳转到登录界面
- 将信息写入配置文件
实现代码(正则表达式——QT中的正则表达式)
// 服务器设置
void Login::on_set_ok_btn_clicked()
{
//获取控件数据
QString ip = ui->address_server->text();
QString port = ui->port_server->text();
// 数据判断
// 服务器IP
// \\d 和 \\. 中第一个\是转义字符, 这里使用的是标准正则
QRegExp regexp(IP_REG);
if(!regexp.exactMatch(ip))
{
QMessageBox::warning(this, "警告", "您输入的IP格式不正确, 请重新输入!");
//清空数据
ui->address_server->clear();
//为了用户友好,设置焦点
ui->address_server->setFocus();
return;
}
// 端口号,通过setPattern重新设置正则规则
regexp.setPattern(PORT_REG);
if(!regexp.exactMatch(port))
{
QMessageBox::warning(this, "警告", "您输入的端口格式不正确, 请重新输入!");
return;
}
// 跳转到登陆界面
ui->stackedWidget->setCurrentWidget(ui->login_page);
// 将配置信息写入配置文件中
m_cm.writeWebInfo(ip, port);
}
保存配置文件信息
1、配置文件格式
{
"login": {
"pwd": "wqq2b4Ild/w=",
"remember": "yes",
"user": "Mi/CvL0kLkQ="
},
"type_path": {
"path": "conf/fileType"
},
"web_server": {
"ip": "192.168.1.27",
"port": "80"
}
}
2、实现代码:
// 服务器信息,写入配置文件
void Common::writeWebInfo(QString ip, QString port, QString path)
{
// web_server信息,QVariant可以放任意数据类型
QMap<QString, QVariant> web_server;
web_server.insert("ip", ip);
web_server.insert("port", port);
// type_path信息
QMap<QString, QVariant> type_path;
type_path.insert("path", m_typePath);
// login信息
QString user = getCfgValue("login", "user");
QString pwd = getCfgValue("login", "pwd");
QString remember = getCfgValue("login", "remember");
QMap<QString, QVariant> login;
login.insert("user", user);
login.insert("pwd", pwd);
login.insert("remember", remember);
// QVariant类作为一个最为普遍的Qt数据类型的联合
// QVariant为一个万能的数据类型--可以作为许多类型互相之间进行自动转换。
QMap<QString, QVariant> json;
json.insert("web_server", web_server);
json.insert("type_path", type_path);
json.insert("login", login);
QJsonDocument jsonDocument = QJsonDocument::fromVariant(json);
if ( jsonDocument.isNull() == true)
{
cout << " QJsonDocument::fromVariant(json) err";
return;
}
//读取文件
QFile file(path);
//如果文件不存在
if( false == file.open(QIODevice::WriteOnly) )
{
cout << "file open err";
return;
}
file.write(jsonDocument.toJson());
file.close();
}
项目中的注册事件
点击注册按钮之后触发的事件
- 取数据
- 校验
- 组织发给server端的数据——将用户输入的注册信息转换成json对象
- 将数据post给server
- 读取server回复的信息,针对不同的回复信息做出相应的处理
确定客户端发送给server端的数据格式
post url:http://127.0.0.1:80/reg
post数据格式:
{
userName:xxxx,
nickName:xxx,
firstPwd:xxx,
phone:xxx,
email:xxx
}
server端nginx添加相应事件的处理
location /reg
{
fastcgi_pass 127.0.0.1:9999;
include fastcgi.conf;
}
设置本机处理相应事件的cgi进程监听9999端口即可。
确定server端返回值的数据格式
成功 |
{"code":"002"} |
该用户已存在 |
{"code":"003"} |
失败 |
{"code":"004"} |
QT中代码
1、login.h中声明将注册信息打包成json格式字符串的函数
QByteArray getRegisterJson(QString name, QString nick, QString passwd, QString phone, QString email);
2、在login.cpp中实现该函数
// 将注册信息打包成json格式字符串
QByteArray Login::getRegisterJson(QString name, QString nick, QString passwd, QString phone, QString email)
{
// {
// userName:xxxx,
// nickName:xxx,
// firstPwd:xxx,
// phone:xxx,
// email:xxx
// }
QMap<QString, QVariant> reg;
reg.insert("userName", name);
reg.insert("nickName", nick);
reg.insert("firstPwd", passwd);
reg.insert("phone", phone);
reg.insert("email", email);
QJsonDocument doc = QJsonDocument::fromVariant(reg);
cout << "reg json" << doc.toJson();
return doc.toJson();
}
注册事件整体代码
// 注册
void Login::on_reg_btn_clicked()
{
// 取值 从输入框取得数据
QString name = ui->name_reg->text();
QString nickName = ui->nike_name->text();
QString passwd = ui->passwd_reg->text();
QString pwd_confirm = ui->pwd_confirm_reg->text();
QString phone = ui->phone->text();
QString email = ui->email->text();
QString address = ui->address->text();
QString port = ui->port->text();
// 数据校验
QRegExp regexp(USER_REG);
if(!regexp.exactMatch(name))
{
QMessageBox::warning(this ,"警告","用户名格式不正确");
//清除输入框中的内容
ui->name_reg->clear();
//光标定位到这里
ui->name_reg->setFocus();
}
regexp.setPattern(USER_REG);
if(!regexp.exactMatch(nickName))
{
QMessageBox::warning(this ,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("昵称格式不正确"));
//清除输入框中的内容
ui->nike_name->clear();
//光标定位到这里
ui->nike_name->setFocus();
}
regexp.setPattern(PASSWD_REG);
if(!regexp.exactMatch(passwd))
{
QMessageBox::warning(this ,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("密码格式不正确"));
//清除输入框中的内容
ui->passwd_reg->clear();
//光标定位到这里
ui->passwd_reg->setFocus();
}
regexp.setPattern(PASSWD_REG);
if(!regexp.exactMatch(pwd_confirm))
{
QMessageBox::warning(this ,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("密码格式不正确"));
//清除输入框中的内容
ui->pwd_confirm_reg->clear();
//光标定位到这里
ui->pwd_confirm_reg->setFocus();
}
regexp.setPattern(PHONE_REG);
if(!regexp.exactMatch(phone))
{
QMessageBox::warning(this ,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("手机号码格式不正确"));
//清除输入框中的内容
ui->phone->clear();
//光标定位到这里
ui->phone->setFocus();
}
regexp.setPattern(EMAIL_REG);
if(!regexp.exactMatch(email))
{
QMessageBox::warning(this ,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("邮箱格式不正确"));
//清除输入框中的内容
ui->email->clear();
//光标定位到这里
ui->email->setFocus();
}
// 组织要发送的json字符串
QByteArray data = setRegisterJson(name, nickName, m_cm.getStrMd5(passwd), phone, email);
// 发送 http 请求协议给server - > post请求
//manager的作用是发送post数据
QNetworkAccessManager *manager = Common::getNetManager();
//制作http协议头。这里使用post的四种格式里面的"application/json"格式来发送数据,因为我们发送的是json数据
QNetworkRequest request;
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
//将携带的数据大小写入header中
request.setHeader(QNetworkRequest::ContentLengthHeader, data.size());
//设置server的url(注意——http://一定要写)
QString url = QString("http://%1:%2/reg").arg(address).arg(port);
request.setUrl(QUrl(url));
QNetworkReply* reply = manager->post(request, data);
// 读server发回的数据
connect(reply, &QNetworkReply::readyRead, [=]()
{
QByteArray json = reply->readAll();
// 成功 {"code":"002"}
// 该用户已存在 {"code":"003"}
// 失败 {"code":"004"}
QString status = m_cm.getCode(json);
if("002" == status)
{
// 成功提示
QMessageBox::information(this, "恭喜", "用户名注册成功");
// 清空注册页面
ui->name_reg->clear();
ui->nike_name->clear();
ui->passwd_reg->clear();
ui->pwd_confirm_reg->clear();
ui->phone->clear();
ui->email->clear();
// 将数据设置到登录窗口控件中
ui->user_login->setText(name);
ui->passwd_login->setText(passwd);
// 切换到登录页面
ui->stackedWidget->setCurrentWidget(ui->login_page);
}
else if("003" == status)
{
QMessageBox::warning(this, "注册失败", QString("[%1]该用户已经存在!!!").arg(name));
}
else
{
QMessageBox::warning(this, "注册失败", "注册失败!!!");
}
// 释放资源
reply->deleteLater();
});
}
补充:post发送数据的四种格式—— 项目(5)(部署web页面实现文件上传操作、post提交数据的四种格式、上传文件流程梳理、安装插件fastdfs-nginx-module、安装storage服务器)
注册用户需要使用的json数据包
// 注册用户需要使用的json数据包
QByteArray Login::setRegisterJson(QString userName, QString nickName,
QString firstPwd, QString phone, QString email)
{
QMap<QString, QVariant> reg;
reg.insert("userName", userName);
reg.insert("nickName", nickName);
reg.insert("firstPwd", firstPwd);
reg.insert("phone", phone);
reg.insert("email", email);
/*json数据如下
{
userName:xxxx,
nickName:xxx,
firstPwd:xxx,
phone:xxx,
email:xxx
}
*/
QJsonDocument jsonDocument = QJsonDocument::fromVariant(reg);
if ( jsonDocument.isNull() )
{
cout << " jsonDocument.isNull() ";
return "";
}
return jsonDocument.toJson();
}
项目server端部署流程
1、设置redis.conf
第一步:关闭绑定ip,如此,可以远程登录
第二步:关闭保护模式,也是为了远程登录
第三步:设置redis进程为守护进程
第四步:设置pid运行的文件目录
第五步:设置log日志的输出位置
第六步:设置数据持久化的保存位置(数据是就花默认以rdb的形式存储)
2、设置json配置文件
配置文件的好处——方便修改。代码中通过读取配置文件信息来进行相关环境的配置(比如设置redis的ip地址和端口号)。
如果服务器变了,我们无需修改代码,只要修改json配置文件即可。
{
"redis":
{
"ip": "127.0.0.1",
"port": "6379"
},
"mysql":
{
"ip": "127.0.0.1",
"port": "3306",
"database": "cloud_disk",
"user": "root",
"password": "root"
},
"dfs_path":
{
"client": "/etc/fdfs/client.conf"
},
"web_server":
{
"ip": "xx.xx.xx.xx",
"port": "80"
},
"storage_web_server":
{
"ip": "xx.xx.xx.xx",
"port": "80"
}
}
3、配置nginx.conf文件
将相应的事件绑定好
location / {
root zyFile2;
index demo.html;
}
location /login{
fastcgi_pass 127.0.0.1:10000;
include fastcgi.conf;
}
location /reg{
fastcgi_pass 127.0.0.1:10001;
include fastcgi.conf;
}
location /upload{
fastcgi_pass localhost:10002;
include fastcgi.conf;
}
location /md5{
fastcgi_pass 127.0.0.1:10003;
include fastcgi.conf;
}
location /myfiles{
fastcgi_pass 127.0.0.1:10004;
include fastcgi.conf;
}
location /dealfile{
fastcgi_pass 127.0.0.1:10005;
include fastcgi.conf;
}
location /sharefiles{
fastcgi_pass 127.0.0.1:10006;
include fastcgi.conf;
}
location /dealsharefile{
fastcgi_pass 127.0.0.1:10007;
include fastcgi.conf;
}
公共类common介绍
声明
class Common : public QObject
{
//不写这个宏,也就没办法使用QT里面的信号槽
Q_OBJECT
public:
Common(QObject* parent = 0);
~Common();
// 让窗口在屏幕中央显示
void moveToCenter(QWidget *tmp);
// 从配置文件中得到相对应的参数
QString getCfgValue(QString title, QString key, QString path = CONFFILE);
// 通过读取文件, 得到文件类型, 存放在typeList
void getFileTypeList();
// 得到文件后缀,参数为文件类型,函数内部判断是否有此类型,如果有,使用此类型,没有,使用other.png
QString getFileType(QString type);
// 登录信息,写入配置文件
void writeLoginInfo(QString user, QString pwd, bool isRemeber, QString path = CONFFILE);
// 服务器信息,写入配置文件
void writeWebInfo(QString ip, QString port, QString path=CONFFILE);
// 获取某个文件的md5码
QString getFileMd5(QString filePath);
// 将某个字符串加密成md5码
QString getStrMd5(QString str = "");
// 产生分隔线
QString getBoundary();
// 得到服务器回复的状态码, 返回值为 "000", 或 "001"
QString getCode(QByteArray json);
// 传输数据记录到本地文件,user:操作用户,name:操作的文件, code: 操作码, path: 文件保存的路径
void writeRecord(QString user, QString name, QString code, QString path = RECORDDIR);
// 得到http通信类对象
static QNetworkAccessManager* getNetManager();
public:
static QStringList m_typeList;
private:
// 文件类型路径
static QString m_typePath;
// 主要保存文件类型的后缀
// http类
static QNetworkAccessManager *m_netManager;
};
QT中的小技巧
如果一个类,不想有界面。可以设置他继承QObject,因为只有Object派生的类,才可以使用QT里面的信号槽
实现——让窗口在屏幕中央显示
// 窗口在屏幕中央显示
void Common::moveToCenter(QWidget *tmp)
{
// 显示窗口
tmp->show();
// 屏幕中间显示
// 使用qApp->desktop();也可以
//通过desktop()获取当前桌面的宽度和高度
QDesktopWidget* desktop = QApplication::desktop();
// 移动窗口 desktop->width() - tmp->width():(当前屏幕的宽度-当前窗口的宽度)/2
tmp->move((desktop->width() - tmp->width())/2, (desktop->height() - tmp->height())/2);
}
实现——从配置文件中得到相对应的参数
/* -------------------------------------------*/
/**
* @brief 从配置文件中得到相对应的参数
*
* @param title 配置文件title名称[title]
* @param key key
* @param path 配置文件路径
*
* @returns
* success: 得到的value
* fail: 空串
*/
/* -------------------------------------------*/
QString Common::getCfgValue(QString title, QString key, QString path)
{
QFile file(path);
// 只读方式打开
if( false == file.open(QIODevice::ReadOnly) )
{
// 打开失败
cout << "file open err";
return "";
}
QByteArray json = file.readAll(); // 读取所有内容
file.close(); // 关闭文件
//判断操作过程中是否出现错误
QJsonParseError error;
// 将来源数据json转化为JsonDocument
// 由QByteArray对象构造一个QJsonDocument对象,用于我们的读写操作
QJsonDocument doc = QJsonDocument::fromJson(json, &error);
if (error.error == QJsonParseError::NoError) // 没有出错
{
//如果转换失败或者是空的
if (doc.isNull() || doc.isEmpty())
{
cout << "doc.isNull() || doc.isEmpty()";
return "";
}
if( doc.isObject()) // 如果对象不为空
{
// QJsonObject json对象,描述json数据中{}括起来部分
QJsonObject obj = doc.object();// 取得最外层这个大对象
//title是我们要解析的子对象的键
QJsonObject tmp = obj.value( title ).toObject();
QStringList list = tmp.keys(); // 取出key列表
//遍历key列表,查找我们要找的那个key(即传入的参数key)
for(int i = 0; i < list.size(); ++i)
{
if( list.at(i) == key )
{
return tmp.value( list.at(i) ).toString();
}
}
}
}
else
{
cout << "err = " << error.errorString();
}
//其他情况返回空串
return "";
}
实现——登录信息,写入配置文件
// 登录信息,写入配置文件
void Common::writeLoginInfo(QString user, QString pwd, bool isRemeber, QString path)
{
// web_server信息
QString ip = getCfgValue("web_server", "ip");
QString port = getCfgValue("web_server", "port");
QMap<QString, QVariant> web_server;
web_server.insert("ip", ip);
web_server.insert("port", port);
// type_path信息
QMap<QString, QVariant> type_path;
type_path.insert("path", m_typePath);
// login信息
QMap<QString, QVariant> login;
// 登陆信息加密
int ret = 0;
// 登陆用户加密
unsigned char encUsr[1024] = {0};
int encUsrLen;
// toLocal8Bit(), 转换为本地字符集,如果windows则为gbk编码,如果linux则为utf-8编码
ret = DesEnc((unsigned char *)user.toLocal8Bit().data(), user.toLocal8Bit().size(), encUsr, &encUsrLen);
if(ret != 0)//加密失败
{
cout << "DesEnc err";
return;
}
// 用户密码加密
unsigned char encPwd[512] = {0};
int encPwdLen;
// toLocal8Bit()——可以将QString转成QByteArray.QByteArray调用data函数转成char*
//DesEnc是一个类,里面有两个功能,加密和解密(自己实现的类)
ret = DesEnc((unsigned char *)pwd.toLocal8Bit().data(), pwd.toLocal8Bit().size(), encPwd, &encPwdLen);
if(ret != 0)
{
cout << "DesEnc err";
return;
}
// 再次加密
// base64转码加密,目的将加密后的二进制转换为base64字符串
login.insert("user", QByteArray((char *)encUsr, encUsrLen).toBase64());
login.insert("pwd", QByteArray((char *)encPwd, encPwdLen).toBase64() );
if(isRemeber == true)
{
login.insert("remember", "yes");
}
else
{
login.insert("remember", "no");
}
// QVariant类作为一个最为普遍的Qt数据类型的联合
// QVariant为一个万能的数据类型--可以作为许多类型互相之间进行自动转换。
QMap<QString, QVariant> json;
json.insert("web_server", web_server);
json.insert("type_path", type_path);
json.insert("login", login);
QJsonDocument jsonDocument = QJsonDocument::fromVariant(json);
if ( jsonDocument.isNull() == true)
{
cout << " QJsonDocument::fromVariant(json) err";
return;
}
//打开配置文件
QFile file(path);
if( false == file.open(QIODevice::WriteOnly) )
{
cout << "file open err";
return;
}
//json内容写入文件,覆盖原来的内容
file.write(jsonDocument.toJson());
file.close();
}
实现——服务器信息,写入配置文件
// 服务器信息,写入配置文件
void Common::writeWebInfo(QString ip, QString port, QString path)
{
// web_server信息,QVariant可以放任意数据类型
QMap<QString, QVariant> web_server;
web_server.insert("ip", ip);
web_server.insert("port", port);
// type_path信息
QMap<QString, QVariant> type_path;
type_path.insert("path", m_typePath);
// login信息
QString user = getCfgValue("login", "user");
QString pwd = getCfgValue("login", "pwd");
QString remember = getCfgValue("login", "remember");
QMap<QString, QVariant> login;
login.insert("user", user);
login.insert("pwd", pwd);
login.insert("remember", remember);
// QVariant类作为一个最为普遍的Qt数据类型的联合
// QVariant为一个万能的数据类型--可以作为许多类型互相之间进行自动转换。
QMap<QString, QVariant> json;
json.insert("web_server", web_server);
json.insert("type_path", type_path);
json.insert("login", login);
QJsonDocument jsonDocument = QJsonDocument::fromVariant(json);
if ( jsonDocument.isNull() == true)
{
cout << " QJsonDocument::fromVariant(json) err";
return;
}
//读取文件
QFile file(path);
//如果文件不存在
if( false == file.open(QIODevice::WriteOnly) )
{
cout << "file open err";
return;
}
file.write(jsonDocument.toJson());
file.close();
}
实现——获取某个文件的md5码
// 获取某个文件的md5码
QString Common::getFileMd5(QString filePath)
{
//读入文件
QFile localFile(filePath);
if (!localFile.open(QFile::ReadOnly))
{
qDebug() << "file open error.";
return 0;
}
QCryptographicHash ch(QCryptographicHash::Md5);
quint64 totalBytes = 0;
quint64 bytesWritten = 0;
quint64 bytesToWrite = 0;
quint64 loadSize = 1024 * 4; //每次读4k
QByteArray buf;
totalBytes = localFile.size();
bytesToWrite = totalBytes;
while (1)
{
if(bytesToWrite > 0)
{
//每次读4k。不要readall
buf = localFile.read(qMin(bytesToWrite, loadSize));
ch.addData(buf);
bytesWritten += buf.length();
bytesToWrite -= buf.length();
buf.resize(0);
}
else
{
break;
}
if(bytesWritten == totalBytes)
{
break;
}
}
localFile.close();
QByteArray md5 = ch.result();
//md5是16进制数组成的,因此需要转换
return md5.toHex();
}
实现——将某个字符串加密成md5码
// 将某个字符串加密成md5码
QString Common::getStrMd5(QString str)
{
QByteArray array;
//md5加密
array = QCryptographicHash::hash ( str.toLocal8Bit(), QCryptographicHash::Md5 );
return array.toHex();
}
实现——得到服务器回复的状态码
// 得到服务器回复的状态码, 返回值为 "000", 或 "001"
QString Common::getCode(QByteArray json)
{
QJsonParseError error;
// 将来源数据json转化为JsonDocument
// 由QByteArray对象构造一个QJsonDocument对象,用于我们的读写操作
QJsonDocument doc = QJsonDocument::fromJson(json, &error);
if (error.error == QJsonParseError::NoError)
{
if (doc.isNull() || doc.isEmpty())
{
cout << "doc.isNull() || doc.isEmpty()";
return "";
}
if( doc.isObject() )
{
// 取得最外层这个大对象
QJsonObject obj = doc.object();
return obj.value( "code" ).toString();
}
}
else
{
cout << "err = " << error.errorString();
}
return "";
}
实现——得到http通信类对象
注意:
该函数在类中被声明为静态的,因为——
一个项目里,只有一个QNetworkAccessManager,我们未来保证他的唯一性,因此将其设置为静态,而不是将其设置为全局变量。因为全局变量不安全。
- 静态变量在用的时候需要先在类外初始化。
- 静态变量在程序运行结束时被释放,因此new出来的QNetworkAccessManager不需要我们操心他什么时候被释放。
// 初始化变量
QString Common::m_typePath = FILETYPEDIR;
QStringList Common::m_typeList = QStringList();
QNetworkAccessManager* Common::m_netManager = new QNetworkAccessManager;
QNetworkAccessManager *Common::getNetManager()
{
// 该对象一般一个应用程序中有一个就够了,无需new多个
return m_netManager;
}
debug小技巧
//自己定义的cout,cout可以输出文件名和行数,方便我们debug
#define cout qDebug() << "[ " << __FILE__ << ":" << __LINE__ << " ] "
sourceinsight的使用
第一步:创建新项目
第二步:选择要看的代码的范围
第三步,开始看代码
服务端注册事件
#include "fcgi_config.h"
#include "fcgi_stdio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "make_log.h" //日志头文件
#include "util_cgi.h"
#include "deal_mysql.h"
#include "cfg.h"
#include "cJSON.h"
#include <sys/time.h>
#define REG_LOG_MODULE "cgi"
#define REG_LOG_PROC "reg"
//解析用户注册信息的json包
int get_reg_info(char *reg_buf, char *user, char *nick_name, char *pwd, char *tel, char *email)
{
int ret = 0;
/*json数据如下
{
userName:xxxx,
nickName:xxx,
firstPwd:xxx,
phone:xxx,
email:xxx
}
*/
//解析json包
//解析一个json字符串为cJSON对象
cJSON * root = cJSON_Parse(reg_buf);
if(NULL == root)
{
LOG(REG_LOG_MODULE, REG_LOG_PROC, "cJSON_Parse err\n");
ret = -1;
goto END;
}
//返回指定字符串对应的json对象
//用户
cJSON *child1 = cJSON_GetObjectItem(root, "userName");
if(NULL == child1)
{
LOG(REG_LOG_MODULE, REG_LOG_PROC, "cJSON_GetObjectItem err\n");
ret = -1;
goto END;
}
//LOG(REG_LOG_MODULE, REG_LOG_PROC, "child1->valuestring = %s\n", child1->valuestring);
strcpy(user, child1->valuestring); //拷贝内容
//昵称
cJSON *child2 = cJSON_GetObjectItem(root, "nickName");
if(NULL == child2)
{
LOG(REG_LOG_MODULE, REG_LOG_PROC, "cJSON_GetObjectItem err\n");
ret = -1;
goto END;
}
strcpy(nick_name, child2->valuestring); //拷贝内容
//密码
cJSON *child3 = cJSON_GetObjectItem(root, "firstPwd");
if(NULL == child3)
{
LOG(REG_LOG_MODULE, REG_LOG_PROC, "cJSON_GetObjectItem err\n");
ret = -1;
goto END;
}
strcpy(pwd, child3->valuestring); //拷贝内容
//电话
cJSON *child4 = cJSON_GetObjectItem(root, "phone");
if(NULL == child4)
{
LOG(REG_LOG_MODULE, REG_LOG_PROC, "cJSON_GetObjectItem err\n");
ret = -1;
goto END;
}
strcpy(tel, child4->valuestring); //拷贝内容
//邮箱
cJSON *child5 = cJSON_GetObjectItem(root, "email");
if(NULL == child5)
{
LOG(REG_LOG_MODULE, REG_LOG_PROC, "cJSON_GetObjectItem err\n");
ret = -1;
goto END;
}
strcpy(email, child5->valuestring); //拷贝内容
END:
if(root != NULL)
{
cJSON_Delete(root);//删除json对象
root = NULL;
}
return ret;
}
//注册用户,成功返回0,失败返回-1, 该用户已存在返回-2
int user_register( char *reg_buf )
{
int ret = 0;
MYSQL *conn = NULL;
//获取数据库用户名、用户密码、数据库标示等信息
char mysql_user[256] = {0};
char mysql_pwd[256] = {0};
char mysql_db[256] = {0};
ret = get_mysql_info(mysql_user, mysql_pwd, mysql_db);
if(ret != 0)
{
goto END;
}
LOG(REG_LOG_MODULE, REG_LOG_PROC, "mysql_user = %s, mysql_pwd = %s, mysql_db = %s\n", mysql_user, mysql_pwd, mysql_db);
//获取注册用户的信息
char user[128];
char nick_name[128];
char pwd[128];
char tel[128];
char email[128];
ret = get_reg_info(reg_buf, user, nick_name, pwd, tel, email);
if(ret != 0)
{
goto END;
}
LOG(REG_LOG_MODULE, REG_LOG_PROC, "user = %s, nick_name = %s, pwd = %s, tel = %s, email = %s\n", user, nick_name, pwd, tel, email);
//connect the database
conn = msql_conn(mysql_user, mysql_pwd, mysql_db);
if (conn == NULL)
{
LOG(REG_LOG_MODULE, REG_LOG_PROC, "msql_conn err\n");
ret = -1;
goto END;
}
//设置数据库编码,主要处理中文编码问题
mysql_query(conn, "set names utf8");
char sql_cmd[SQL_MAX_LEN] = {0};
sprintf(sql_cmd, "select * from user where name = '%s'", user);
//查看该用户是否存在
int ret2 = 0;
//返回值: 0成功并保存记录集,1没有记录集,2有记录集但是没有保存,-1失败
ret2 = process_result_one(conn, sql_cmd, NULL); //指向sql查询语句
if(ret2 == 2) //如果存在
{
LOG(REG_LOG_MODULE, REG_LOG_PROC, "【%s】该用户已存在\n");
ret = -2;
goto END;
}
//当前时间戳
struct timeval tv;
struct tm* ptm;
char time_str[128];
//使用函数gettimeofday()函数来得到时间。它的精度可以达到微妙
gettimeofday(&tv, NULL);
ptm = localtime(&tv.tv_sec);//把从1970-1-1零点零分到当前时间系统所偏移的秒数时间转换为本地时间
//strftime() 函数根据区域设置格式化本地时间/日期,函数的功能将时间格式化,或者说格式化一个时间字符串
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", ptm);
//sql 语句, 插入注册信息
sprintf(sql_cmd, "insert into user (name, nickname, password, phone, createtime, email) values ('%s', '%s', '%s', '%s', '%s', '%s')", user, nick_name, pwd, tel, time_str ,email);
if(mysql_query(conn, sql_cmd) != 0)
{
LOG(REG_LOG_MODULE, REG_LOG_PROC, "%s 插入失败:%s\n", sql_cmd, mysql_error(conn));
ret = -1;
goto END;
}
END:
if(conn != NULL)
{
mysql_close(conn); //断开数据库连接
}
return ret;
}
int main()
{
//阻塞等待用户连接
while (FCGI_Accept() >= 0)
{
char *contentLength = getenv("CONTENT_LENGTH");
int len;
printf("Content-type: text/html\r\n\r\n");
if( contentLength == NULL )
{
len = 0;
}
else
{
len = atoi(contentLength); //字符串转整型
}
if (len <= 0)//没有登陆用户信息
{
printf("No data from standard input.<p>\n");
LOG(REG_LOG_MODULE, REG_LOG_PROC, "len = 0, No data from standard input\n");
}
else //获取登陆用户信息
{
char buf[4*1024] = {0};
int ret = 0;
char *out = NULL;
ret = fread(buf, 1, len, stdin); //从标准输入(web服务器)读取内容
if(ret == 0)
{
LOG(REG_LOG_MODULE, REG_LOG_PROC, "fread(buf, 1, len, stdin) err\n");
continue;
}
LOG(REG_LOG_MODULE, REG_LOG_PROC, "buf = %s\n", buf);
//注册用户,成功返回0,失败返回-1, 该用户已存在返回-2
/*
注册:
成功:{"code":"002"}
该用户已存在:{"code":"003"}
失败:{"code":"004"}
*/
ret = user_register( buf );
if (ret == 0) //登陆成功
{
//返回前端注册情况, 002代表成功
out = return_status("002");//util_cgi.h
}
else if(ret == -1)
{
//返回前端注册情况, 004代表失败
out = return_status("004");//util_cgi.h
}
else if(ret == -2)
{
out = return_status("003");//util_cgi.h
}
if(out != NULL)
{
printf(out); //给前端反馈信息
free(out); //记得释放
}
}
}
return 0;
}