操作系统与网络 2019-4-16

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 文件中定义几个宏
// 定义SQL语句的最大长度
#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;
}
  • 5.在 PackDef.h 中定义几个宏;
// 定义 登陆 成功或者失败的标志
#define login_fail			0
#define login_success		1

1.3 在SQL中完成下述代码,添加一个 view 视图

  • 1.创建视图
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;
}
  • 6.在 PackDef.h 中定义几个宏
// 定义 设置房间信息 成功或者失败的标志
#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->RegisterRq(0,(char*)&srr);
	pKernel->LoginRq(0,(char*)&srr);
	system("pause");
	return true;
}
  • 4.下断点进行测试。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值