1.继续完成服务器
1.1 完成注册请求函数 RegisterRq
- 1.获取注册请求的结构体对象;
- 2.定义SQL语句数组;
- 3.定义注册回复结构体对象;
- 4.给回复对象的结构体协议头赋值;
- 5.获取用户信息,并将用户信息放入数据库中;
- 6.判断来的数据包是主播的还是观众的,两个数据存储的位置不同,因此需要进行判断;
- 7.若为主播,拼接SQL语句;
- 8.若注册成功则分配room;
- 9.观众与主播类似;
- 10.发送回复信息包;
bool TCPKernel::RegisterRq(SOCKET sock,char* szbuf)
{
STRU_RESIGER_RQ* p_srr = (STRU_RESIGER_RQ*)szbuf;
char sz_sql[DEF_SQLLEN] = {0};
STRU_RESISTER_RS srr;
srr.m_n_type = _DEF_PROTOCOL_REGISTER_RS;
srr.m_sz_result = register_fail;
if(p_srr->m_sz_role == role_author)
{
sprintf_s(sz_sql, "insert into author values(%lld, '%s', '%s')",
p_srr->m_id, p_srr->m_sz_name, p_srr->m_sz_password);
if(m_sql.UpdateMySql(sz_sql))
{
sprintf_s(sz_sql, "insert into room(r_name, a_id) values('%s', %lld)",
p_srr->m_sz_name, p_srr->m_id);
m_sql.UpdateMySql(sz_sql);
srr.m_sz_result = register_success;
}
}
else if(p_srr->m_sz_role == role_audience)
{
sprintf_s(sz_sql, "insert into audience values(%lld, '%s', '%s')",
p_srr->m_id, p_srr->m_sz_name, p_srr->m_sz_password);
if(m_sql.UpdateMySql(sz_sql))
{
srr.m_sz_result = register_success;
}
}
m_p_net->SendData(sock, (char*)&srr, sizeof(srr));
return true;
}
- 10.上述代码进行编译之前需要在 PackDef.h 文件中定义几个宏
#define DEF_SQLLEN 300
#define register_fail 0
#define register_success 1
1.2 完成登陆请求包
- 1.获取登陆请求包的结构体指针;
- 2.将用户信息取出来,与数据库中的数据进行比较;
- 3.主播与观众登陆的请求处理基本一致;
- 4.发送登陆的回复包;
bool TCPKernel::LoginRq(SOCKET sock,char* szbuf)
{
STRU_LOGIN_RQ* p_slr = (STRU_LOGIN_RQ*)szbuf;
char sz_sql[DEF_SQLLEN] = {0};
STRU_LOGIN_RS slr;
slr.m_n_type = _DEF_PROTOCOL_LOGIN_RS;
slr.m_sz_result = login_fail;
list<string> ls_str;
if(p_slr->m_sz_role == role_author)
{
sprintf_s(sz_sql, "select a_password from author where a_id = %lld or a_name = '%s'",
p_slr->m_id, p_slr->m_sz_name);
m_sql.SelectMySql(sz_sql, 1, ls_str);
if(ls_str.size() > 0)
{
string str_password = ls_str.front();
ls_str.pop_front();
if(0 == strcmp(p_slr->m_sz_password, str_password.c_str()))
{
slr.m_sz_result = login_success;
}
}
}
else if(p_slr->m_sz_role == role_audience)
{
sprintf_s(sz_sql, "select a_password from audience where a_id = %lld or a_name = '%s'",
p_slr->m_id, p_slr->m_sz_name);
m_sql.SelectMySql(sz_sql, 1, ls_str);
if(ls_str.size() > 0)
{
string str_password = ls_str.front();
ls_str.pop_front();
if(0 == strcmp(p_slr->m_sz_password, str_password.c_str()))
{
slr.m_sz_result = login_success;
}
}
}
m_p_net->SendData(sock, (char*)&slr, sizeof(slr));
return true;
}
#define login_fail 0
#define login_success 1
1.3 在SQL中完成下述代码,添加一个 view 视图
create view myview as (select author_id, a_name, r_id, r_name from author inner join room on author.a_id = room.a_id);
select r_id, r_name from myview;
1.4 完成获取房间信息请求函数 GetRoomInfoRq
- 1.获取 STRU_GETROOMINFO_RQ 结构体指针;
- 2.定义SQL语句存储空间;
- 3.定义 STRU_GETROOMINFO_RS 结构体对象;
- 4.使用SQL语句显示指针中的a_name对应的房间的信息;
- 5.用一个list来存储房间信息,若主播存在则将信息装入到回复包中;
bool TCPKernel::GetRoomInfoRq(SOCKET sock,char* szbuf)
{
STRU_GETROOMINFO_RQ* p_sgr = (STRU_GETROOMINFO_RQ*)szbuf;
char sz_sql[DEF_SQLLEN] = {0};
list<string> ls_str;
STRU_GETROOMINFO_RS sgr;
sgr.m_nType = _DEF_PROTOCOL_GETROOMINFO_RQ;
sprintf_s(sz_sql, "select r_id, r_name from myview where a_name = '%s'",
p_sgr->m_szName);
m_sql.SelectMySql(sz_sql, 2, ls_str);
if(ls_str.size() > 0)
{
string str_id = ls_str.front();
ls_str.pop_front();
string str_name = ls_str.front();
ls_str.pop_front();
sgr.m_roomid = atoi(str_id.c_str());
strcpy_s(sgr.m_szRoomName, sizeof(sgr.m_szRoomName), str_name.c_str());
}
m_p_net->SendData(sock, (char*)&sgr, sizeof(sgr));
return true;
}
1.5 完成设置房间信息请求函数 SetRoomInfoRq
- 1.获取 STRU_SETROOMINFO_RQ 指针;
- 2.定义存储SQL语句的空间;
- 3.定义 STRU_SETROOMINFO_RS 对象;
- 4.使用 update SQL语句来更改 myview 视图中的信息;
- 5.发送回复包;
bool TCPKernel::SetRoomInfoRq(SOCKET sock,char* szbuf)
{
STRU_SETROOMINFO_RQ* p_ssq = (STRU_SETROOMINFO_RQ*)szbuf;
char sz_sql[DEF_SQLLEN] = {0};
STRU_SETROOMINFO_RS ssr;
ssr.m_nType = _DEF_PROTOCOL_SETROOMINFO_RS;
ssr.m_szResult = setroom_fail;
sprintf_s(sz_sql, "update myview set r_name = '%s' where a_name = '%s'",
p_ssq->m_szRoomName, p_ssq->m_szName);
if(m_sql.UpdateMySql(sz_sql))
{
ssr.m_szResult = setroom_success;
}
m_p_net->SendData(sock, (char*)&ssr, sizeof(ssr));
return true;
}
#define setroom_fail 0
#define setroom_success 1
1.6 在 TCPNet 的 SendData 函数中
- 1.判断包的信息的大小,若发送不成功则返回false;
- 2.判断传入参数是否正确,不正确则返回false;
bool TCPNet::SendData(SOCKET sock,char* szbuf,int nlen)
{
if(!sock || !szbuf || nlen <= 0)
return false;
if(send(sock, (const char*)&nlen, sizeof(nlen), 0) < 0)
return false;
if(send(sock,szbuf,nlen,0) < 0)
return false;
return true;
}
1.7 进行程序的检测
- 1.自定义一个 STRU_RESIGER_RQ 来进行注册请求的检测;
- 2.先使用 RegisterRq 函数向数据库中注册一个主播类型的数据;
- 3.再使用 LoginRq 函数来检测是否能从数据库成功获取该信息;
int main()
{
TCPKernel *pKernel = new TCPKernel;
if(!pKernel->Open())
{
cout << "错误码:"<<GetLastError();
system("pause");
return false;
}
STRU_RESIGER_RQ srr;
srr.m_n_type = _DEF_PROTOCOL_LOGIN_RQ;
srr.m_id = 15046691259;
strcpy_s(srr.m_sz_name,45,"SLAM");
strcpy_s(srr.m_sz_password,45,"123456");
srr.m_sz_role = 0;
pKernel->LoginRq(0,(char*)&srr);
system("pause");
return true;
}