用户注册
在创建Json对象的数据后,客户端和服务端就可以依据这个类型的数据进行通信了。我们通过解析Json对象val中的cmd指令,也就是命令,来判断客户端是想要进行什么操作(用户注册?登录?聊天?),从而执行对应的函数操作。
if(cmd == "register"){
server_register(bev,val); //执行用户注册对应的函数
}
在用户注册的回调函数server_register
中,我们首先需要连接用户数据库user
,来判断该用户信息是否已经在数据库中。如果用户已经存在,那么就不用注册,回复客户端:注册失败。如果用户不存在,我们就需要将注册的信息(用户账号、密码)输入到创建的用户table中。
void Server::server_register(struct bufferevent *bev,Json::Value val){
chatdb->my_database_connect("user"); //连接user数据库
string username = val["user"].asString();
if(chatdb->my_database_user_exist(username)){ //用户存在
Json::Value val;
val["cmd"] = "register_reply"; //返回Json格式的数据,告诉客户端 注册失败
val["result"] = "failure";
string reply = Json::FastWriter().write(val); //将需回复的Json格式的val转变成string格式
if(bufferevent_write(bev,reply.c_str(),strlen(reply.c_str()))){
cout << "bufferevent_write error" << endl;
} //发送回复信息给客户端
}else{ //用户不存在,则注册
string username = val["user"].asString();
string userpassword = val["password"].asString();
chatdb->my_database_user_password(username,userpassword);
Json::Value val;
val["cmd"] = "register_reply";
val["result"] = "success";
string reply = Json::FastWriter().write(val); //将需回复的Json格式的val转变成string格式
if(bufferevent_write(bev,reply.c_str(),strlen(reply.c_str()))){
cout << "bufferevent_write error" << endl;
} //发送回复信息给客户端
}
chatdb->my_database_disconnect(); //用完user数据库后,断开连接,方便下次别的数据库调用
}
可以看到,当用户已经存在时,服务端回复客户端:{“cmd”:“register_reply”,“result”:“failure”}的Json数据。当用户不存在时,就回复客户端:{“cmd”:“register_reply”,“result”:“sucdess”}的Json数据。
具体函数实现
my_database_connect实现
mysql = mysql_init(NULL);
mysql = mysql_real_connect(mysql,"localhost","root","root",name,0,NULL,0);
if(mysql == NULL){
cout << "mysql_real_connect failure" << endl; //为空连接失败
}
//如果初始化连接成功,直接设置中文,避免中文出错
//设置中文
if(mysql_query(mysql,"set names utf8;") != 0){
cout << "mysql_query error" << endl;
}
其中mysql_init
是MYSQL对象的初始化,分配或初始化与mysql_real_connect()
相适应的MYSQL对象。如果mysql_init()分配了新的对象,应当在程序中调用mysql_close() 来关闭连接,以释放对象。
MYSQL *mysql_init(MYSQL *mysql)
返回值:
//初始化的MYSQL*句柄。如果无足够内存以分配新的对象,返回NULL。 错误,在内存不足的情况下,返回NULL。
说明:
//如果mysql是NULL指针,该函数将分配、初始化、并返回新对象。
//否则,将初始化对象,并返回对象的地址。
mysql_real_connect
用来连接创建的数据库
MYSQL *mysql_real_connect (MYSQL *mysql,
const char *host,
const char *user,
const char *passwd,
const char *db,
unsigned int port,
const char *unix_socket,
unsigned long client_flag)
mysql_query
用来执行MYSQL中SQL语句
int mysql_query(MYSQL *mysql, const char *query)
//query为执行的SQL语句对应的字符长串
my_database_user_exist实现
通过在user数据库中执行show tables like 张三
,可以查询是否有张三的信息表,从而判断该用户是否存在于user数据库中。当然执行完mysql_query后需要执行MYSQL_RES
来存储执行完命令后查询到的数据。mysql_store_result()
将mysql_query()
查询的全部结果读取到客户端,分配1个MYSQL_RES结构。然后通过mysql_fetch_row获取结果集中的下一行,通过对该结果处理获取想要的数据。
char sql[128] = {0};
sprintf(sql,"show tables like '%s';",name.c_str()); //查看数据库中是否有name的信息
if(mysql_query(mysql,sql) != 0){
cout << "mysql_query error" << endl;
}
MYSQL_RES *res = mysql_store_result(mysql); //获取上述命令结果
MYSQL_ROW row = mysql_fetch_row(res);
my_database_user_password实现
通过执行create table
创建用户的信息表,从代码可以看出,用户的信息有密码password、朋友friend以及群chatrgoup。创建完用户信息表格后,将密码插入该用户的信息表中。
char sql[128] = {0};
sprintf(sql,"create table %s (password varchar(16),friend varchar(4096),chatgroup varchar(4096)) character set utf8;"
,name.c_str());
if(mysql_query(mysql,sql) != 0){
cout << "mysql_query error" << endl;
}
memset(sql,0,sizeof(sql));
sprintf(sql,"insert into %s (password) values ('%s');",name.c_str(),password.c_str()); //向用户表中插入密码
if(mysql_query(mysql,sql) != 0){
cout << "mysql_query error" << endl;
}
最后的最后,释放掉数据库连接,毕竟有connect就肯定有disconnect,mysql_init初始化了一个MYSQL对象,执行完操作后,需要mysql_close(对象名)
,释放连接,方便下次调用。