这里我们设计一个利用socket多路复用方式的局域网通讯系统。
要求:
1、以C/S架构为基础。
2、服务器实现针对数据库信息的管理,同时建立基于TCP的socket通信。
3、客户端实现与服务器信息的交互,同时也需要实现客户端与客户端的信息交互。
整体结构:
image.png
运行效果:
image.png
image.png
image.png
image.png
image.png
image.png
这里我们先实现基础的注册效果
服务器实现
服务器主要需要实现几个基本功能:
1、数据库基本操作
2、服务器建立
3、数据通信
因为通信这里依然采用之前的socket的多路复用方式,基础实现所以这里不再做介绍,可以参考之前写的章节:Qt 基于TCP的socket通信实现(类似IO多路复用)
数据库基本操作:
1、建立数据库
DataBase::DataBase()
{
//创建一个mysql的数据库连接
sqldb = QSqlDatabase::addDatabase("QMYSQL");
sqldb.setDatabaseName("mydata");
sqldb.setHostName("localhost");
sqldb.setUserName("root");
sqldb.setPassword("123456");
sqldb.setPort(3306);
if( !sqldb.open())
{
QMessageBox::warning(NULL,"error",sqldb.lastError().text());
}
}
利用QSqlQuery实现数据库的动态sql查询
void DataBase::insertUser(struct DBUser user)
{
QSqlQuery query;
//准备预编译的语句
query.prepare("insert into user(userid,display,sign,sex,birthday,phone,mail,pwd,face) \
values( null , \
:display, \
:sign, \
:sex, \
:birthday, \
:phone, \
:mail, \
:pwd, \
:face)");
//绑定数据
query.bindValue(":display",QVariant(user.display));
query.bindValue(":sign",QVariant(user.sign));
query.bindValue(":sex",QVariant(QString::number(user.sex)));
query.bindValue(":birthday",QVariant(user.birthday));
query.bindValue(":phone",QVariant(user.phone));
query.bindValue(":mail",QVariant(user.mail));
query.bindValue(":pwd",QVariant(user.pwd));
query.bindValue(":face",QVariant(QString::number(user.face)));
query.exec();//发送sql语句
}
2、服务器的建立
这里与之前的操作无差别,略
3、数据通信
需要在原有的通信结构基础上实现两个主体功能
1)处理用户消息
主要是为了区分不同的客户端信息,例如注册消息、登录消息、设置我们还可以在之后扩展更多的消息类型,这里我们可以留一个扩展位置,方便后续功能集成。
//处理用户消息
void Client::receiveMessage(QMap<QString,QString> message)
{
int requestKind = message["requestKind"].toInt();
if(REGISTER == requestKind)
{
//注册消息
doRegister(message);
}
return;
}
2)注册消息的格式组合
服务器通过拼接数据格式,进一步调用数据库操作类的insertUser(userinfo)实现,数据插入,同时需要获取是否成功的消息反馈,用于返回客户端,这里我反馈是注册的id。
//注册消息
void Client::doRegister(QMap<QString,QString> message)
{
//准备数据
DBUser userinfo;
DataBase* db = DataBase::getInstance();
userinfo.display = message["display"];
userinfo.sign = message["sign"];
userinfo.sex = message["sex"].toInt();
userinfo.birthday = QDate::fromString(message["birthday"],"yyyy-MM-dd");
userinfo.phone = message["phone"];
userinfo.mail = message["mail"];
userinfo.pwd = message["pwd"];
userinfo.face = message["face"].toInt();
//插入数据库
db->insertUser(userinfo);
//取得插入后的最大userid(即,刚才登陆的用户的id)
QString userid = db->getMaxUserid();
//反馈注册成功消息
QMap<QString,QString> msg;
msg["requestKind"] = QString::number(REGISTER_SUCCESS);
msg["userid"] = userid;
_clientSocket->sendMessage(msg);
}
运行效果:
客户端连接服务器信息界面
服务器Demo
注册界面
数据库测试信息
注册调试信息
注册运行效果.gif
界面部分使用了仿QQ界面的登录界面,由于登录还没有集成,只需要点击注册账号即可进行注册即可(由于没有将连接服务器写死,所以设置了连接配置界面,需要先连接服务器)。
完整代码实现(包含界面类):











网友评论