这里我是一步一步写的,写注册和登录的时候并没有考虑到用结构体,导致后续比较麻烦,所以用了三个端口分别处理登录,注册和登录成功后发送数据。读者在使用代码前要在桌面前放一个pic.png的背景图。代码中的图片路径也要修改,我的桌面路径实在D盘的,根据自己电脑的情况改。
运行前需要创建表,把pro文件中加入network和sql,把代码中的客户端代码的ip改为自己用到的服务器的ip。
阐述一下代码流程:
首先先启动服务器端,客户端运行后出现下面的界面
如果用户没有id,可以点击reg注册,如果有可以直接log登录。点击reg后出现下面的界面
这里的的name没有用到,如果读者想用的话可以在点击finish后把这项信息加入,password和它下面一行的确认密码必须输入一样的才可以点击finish发送给服务器端成功,如果不一样会提示两次输入不同
输入相同后点击finish,然后服务器端会发过来一个id号,同时将id号插入到服务器端用户数据的数据库。
点击OK返回原来的界面,输入id,密码,点击log,程序会将id和密码打包发给服务器,如果不对:
输入正确后:
点击表头可以排序。
在使用前需要自己先创建一个数据库。最好名字是my_stu_system_usrinfo,用户数据表是info,学生数据表是stu,不然的话和代码中名字不一样还要修改。
可以先在一个文件中执行下面代码,生成stu表
QSqlDatabase db_stu1=QSqlDatabase::addDatabase("QSQLITE");
db_stu1.setDatabaseName("my_stu_system_usrinfo");
db_stu1.open();
QSqlQuery query2(db_stu1);
query2.exec("create table stu(id int primary key,name char,age int,sex char,score int)");
query2.exec("insert into stu values(10001,'lisi',19,'w',85)");
query2.exec("insert into stu values(10002,'wangwu',17,'m',87)");
query2.exec("insert into stu values(10003,'zhaoliu',21,'w',84)");
query2.exec("insert into stu values(10004,'tianqi',16,'m',90)");
query2.exec(QObject::tr("select * from stu"));
while(query2.next()){
qDebug()<<query2.value(0).toInt();
qDebug()<<query2.value(1).toString();
qDebug()<<query2.value(2).toInt();
qDebug()<<query2.value(3).toString();
qDebug()<<query2.value(4).toInt();
}
然后执行下面代码创建info用户数据表,这是创建了一个id1000,密码0的用户。注意如果这两个代码在一个main中执行,一定要先注释上面的代码,不然会报错。
QSqlDatabase db_stu=QSqlDatabase::addDatabase("QSQLITE");
db_stu.setDatabaseName("my_stu_system_usrinfo");
db_stu.open();
QSqlQuery query(db_stu);
query.exec("create table info(id int primary key,pass char)");
query.prepare("insert into info(id,pass)" "values(:id,:pass)");
query.prepare("insert into info(id,pass)" "values(:id,:password)");
query.addBindValue(1000);
QString s="0";
query.addBindValue(s);
query.exec();
query.exec(QObject::tr("select * from info"));
int num=0;
while(query.next()){
num++;
qDebug()<<query.value(0).toInt();
qDebug()<<query.value(1).toString();
}
注意在使用前将.pro文件中加入network和sql
服务器代码:
widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTextEdit>
#include <QSqlQuery>
typedef struct net_stu_info{
char code;
int id;
char name[30];
int age;
char sex;
int score;
}stuInfo_t;
class Widget : public QWidget
{
Q_OBJECT
private:
QTcpServer* server;
QTcpSocket* socket;
QTcpServer* server_log;
QTcpSocket* socket_log;
QTcpServer* server_log_succ;
QTcpSocket* socket_log_succ;
QTextEdit* text;
QSqlDatabase db_info;
public:
Widget(QWidget *parent = nullptr);
void init();
void init_sql();
void init_sql_info();
int search_num();
void insert_usr(int id,QString password);
int judge_log(int id,QString password);
void send_info();
~Widget();
};
#endif // WIDGET_H
widget.cpp:
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
init();
init_sql();
}
void Widget::init(){
this->setWindowTitle("server");
this->setFixedSize(800,600);
this->server=new QTcpServer(this);
this->server_log=new QTcpServer(this);
this->server_log_succ=new QTcpServer(this);
this->socket=new QTcpSocket(this);
this->socket_log=new QTcpSocket(this);
this->socket_log_succ=new QTcpSocket(this);
this->text=new QTextEdit(this);
text->move(100,80);
text->resize(600,400);
text->setReadOnly(1);
connect(server,&QTcpServer::newConnection,[=](){
socket=server->nextPendingConnection();
text->append("客户连接...");
connect(socket,&QTcpSocket::readyRead,[=](){
QString recvmsg=socket->readAll();
text->append("客户端发送:"+recvmsg);
int id=search_num();
insert_usr(id,recvmsg);
QString id_s=QString::number(id,10);
socket->write(id_s.toUtf8());
});
connect(socket,&QTcpSocket::disconnected,[=](){
text->append("客户端断开连接...");
socket->deleteLater();
});
});
connect(server_log,&QTcpServer::newConnection,[=](){
socket_log=server_log->nextPendingConnection();
text->append("客户尝试登陆...");
connect(socket_log,&QTcpSocket::readyRead,[=](){
QString recvmsg=socket_log->readAll();
text->append("客户端发送:"+recvmsg);
QStringList list=recvmsg.split("?p=");
int id=list[0].toInt();
QString password=list[1].toLatin1().data();
int ret=judge_log(id,password);
QString str;
if(!ret){
str="OK";
}else{
str="NO";
}
qDebug()<<recvmsg.toUtf8();
socket_log->write(str.toUtf8());
});
connect(socket_log,&QTcpSocket::disconnected,[=](){
text->append("客户端断开登录...");
socket_log->deleteLater();
});
});
connect(server_log_succ,&QTcpServer::newConnection,[=](){
socket_log_succ=server_log_succ->nextPendingConnection();
text->append("客户登录...");
send_info();
connect(socket_log_succ,&QTcpSocket::readyRead,[=](){
QString recvmsg=socket_log_succ->readAll();
text->append("客户端发送:"+recvmsg);
});
connect(socket_log_succ,&QTcpSocket::disconnected,[=](){
text->append("客户端退出...");
socket_log_succ->deleteLater();
});
});
unsigned int port_log=7777;
server_log->listen(QHostAddress::Any,port_log);
unsigned int port=9999;
server->listen(QHostAddress::Any,port);
unsigned int port_log_succ=6666;
server_log_succ->listen(QHostAddress::Any,port_log_succ);
}
void Widget::send_info(){
QSqlQuery query(db_info);
query.exec(QObject::tr("select * from stu"));
stuInfo_t stu;
while(query.next()){
memset(&stu,0,sizeof(stuInfo_t));
stu.id=query.value(0).toInt();
QByteArray array_name=query.value(1).toString().toLatin1();
memcpy(&stu.name,array_name.data(),array_name.length());
stu.age=query.value(2).toInt();
QByteArray array_sex=query.value(3).toString().toLatin1();
memcpy(&stu.sex,array_sex.data(),1);
stu.score=query.value(4).toInt();
QByteArray array;
array.resize(sizeof(stuInfo_t));
memcpy(array.data(),&stu,sizeof(stuInfo_t));
socket_log_succ->write(array);
}
}
void Widget::init_sql(){
QString error="open error";
db_info=QSqlDatabase::addDatabase("QSQLITE");
db_info.setDatabaseName("my_stu_system_usrinfo");
if(!db_info.open())
throw error;
}
int Widget::search_num(){
QSqlQuery query(db_info);
int num=0;
query.exec(QObject::tr("select * from info"));
while(query.next()){
num++;
qDebug()<<query.value(0).toInt();
qDebug()<<query.value(1).toString();
}
return num+1000;
}
int Widget::judge_log(int id,QString password){
QSqlQuery query(db_info);
query.prepare("select * from info where pass=? and id=?");
query.addBindValue(password);
query.addBindValue(id);
query.exec();
if(!query.next()){
return -1;
}
return 0;
}
void Widget::insert_usr(int id,QString password){
QSqlQuery query(db_info);
query.prepare("insert into info(id,pass)""values(:id,:password)");
query.addBindValue(id);
query.addBindValue(password);
query.exec();
search_num();
}
Widget::~Widget()
{
}
main.cpp:
#include "widget.h"
#include <QApplication>
#include <QSqlQuery>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
客户端代码:
log_dialog.h:
#ifndef LOG_DIALOG_H
#define LOG_DIALOG_H
#include <QDialog>
#include <QTableView>
#include <QStandardItemModel>
#include <QPushButton>
#include <QGridLayout>
#include <QVBoxLayout>
#include <QTcpSocket>
#include <QSqlQuery>
typedef struct net_stu_info{
char code;
int id;
char name[30];
int age;
char sex;
int score;
}stuInfo_t;
class log_interface : public QDialog
{
Q_OBJECT
private:
int id=0;
QStandardItemModel* model;
QTableView* view;
QVBoxLayout* vlayout;
QTcpSocket* socket;
public:
explicit log_interface(QWidget *parent = nullptr);
void setid(int id);
void init();
void create_row(stuInfo_t* stu);
signals:
void chou();
};
#endif // LOG_DIALOG_H
reg_interface.h:
#ifndef REG_INTERFACE_H
#define REG_INTERFACE_H
#include <QDialog>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include <QSqlQuery>
#include <QTcpSocket>
#include <QHostAddress>
class reg_interface : public QDialog
{
Q_OBJECT
public:
explicit reg_interface(QWidget *parent = nullptr);
void init_q();
signals:
void reg_fin_signals();
void reg_cancel_signals();
private:
QPushButton* fin_btn;
QPushButton* cancel_btn;
QLabel* cre_name;
QLabel* fir_password;
QLabel* confirm_password;
QLineEdit* cre_name_line;
QLineEdit* fir_password_line;
QLineEdit* confirm_password_line;
QTcpSocket* socket;
};
#endif // REG_INTERFACE_H
widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include "reg_interface.h"
#include <QTcpSocket>
#include "log_dialog.h"
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
public slots:
void show_reg_interface();
private:
QLabel* usrname;
QLabel* password;
QLineEdit* usrnameline;
QLineEdit* passwordline;
QPushButton* reg_btn;
QPushButton* log_btn;
reg_interface* reg_dialog;
QTcpSocket* socket;
log_interface* log_dialog;
};
#endif // WIDGET_H
log_dialog.cpp:
#include "log_dialog.h"
log_interface::log_interface(QWidget *parent) : QDialog(parent)
{
init();
}
void log_interface::setid(int id){
this->id=id;
}
void log_interface::init(){
QPalette p = this->palette();
p.setBrush(QPalette::Window,QBrush(QPixmap("D:/UserData/Desktop/pic.png")));
this->setPalette(p);
this->setWindowTitle("stu system");
this->setFixedSize(1024,768);
model=new QStandardItemModel(this);
view=new QTableView(this);
this->socket=new QTcpSocket(this);
QString ip="192.168.70.90";
unsigned int port=6666;
this->socket->connectToHost(ip,port);
vlayout=new QVBoxLayout(this);
model->setColumnCount(5);
model->setHeaderData(0,Qt::Horizontal,QStringLiteral("学号"));
model->setHeaderData(1,Qt::Horizontal,QStringLiteral("姓名"));
model->setHeaderData(2,Qt::Horizontal,QStringLiteral("年龄"));
model->setHeaderData(3,Qt::Horizontal,QStringLiteral("性别"));
model->setHeaderData(4,Qt::Horizontal,QStringLiteral("分数"));
view->setModel(model);
connect(socket,&QTcpSocket::readyRead,[=](){
QByteArray array=socket->read(sizeof(stuInfo_t));
array.resize(sizeof(stuInfo_t));
stuInfo_t stu;
while(!array.isEmpty()){
array.resize(sizeof(stuInfo_t));
memset(&stu,0,sizeof(stuInfo_t));
memcpy(&stu,array,sizeof(stuInfo_t));
create_row(&stu);
array=socket->read(sizeof(stuInfo_t));
}
});
view->setModel(model);
view->setSortingEnabled(true);
view->setEditTriggers(QAbstractItemView::NoEditTriggers);
vlayout->addWidget(view);
}
void log_interface::create_row(stuInfo_t *stu){
static int row=0;
view->setRowHeight(row,50);
QStandardItem* item0=new QStandardItem(tr("%1").arg(stu->id));
QStandardItem* item1=new QStandardItem(tr("%1").arg(stu->name));
QStandardItem* item2=new QStandardItem(tr("%1").arg(stu->age));
QStandardItem* item3=new QStandardItem(tr("%1").arg(stu->sex));
QStandardItem* item4=new QStandardItem(tr("%1").arg(stu->score));
model->setItem(row,0,item0);
model->setItem(row,1,item1);
model->setItem(row,2,item2);
model->setItem(row,3,item3);
model->setItem(row,4,item4);
model->item(row,0)->setTextAlignment(Qt::AlignCenter);
model->item(row,1)->setTextAlignment(Qt::AlignCenter);
model->item(row,2)->setTextAlignment(Qt::AlignCenter);
model->item(row,3)->setTextAlignment(Qt::AlignCenter);
model->item(row,4)->setTextAlignment(Qt::AlignCenter);
row++;
view->setModel(model);
}
reg_interface.cpp:
#include "reg_interface.h"
#include <QGridLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QTcpSocket>
#include <QDebug>
reg_interface::reg_interface(QWidget *parent) : QDialog(parent)
{
this->setWindowTitle("reg");
this->setFixedSize(300,200);
init_q();
}
void reg_interface::init_q(){
cre_name=new QLabel("name:",this);
fir_password=new QLabel("password:",this);
confirm_password=new QLabel("input again:");
cre_name_line=new QLineEdit(this);
fir_password_line=new QLineEdit(this);
confirm_password_line=new QLineEdit(this);
QPalette p = this->palette();
p.setBrush(QPalette::Window,QBrush(QPixmap("D:/UserData/Desktop/pic.png")));
this->setPalette(p);
fin_btn=new QPushButton("finish",this);
cancel_btn=new QPushButton("cancel",this);
this->socket=new QTcpSocket(this);
QGridLayout* uplayout=new QGridLayout;
uplayout->addWidget(cre_name,0,0);
uplayout->addWidget(cre_name_line,0,1);
uplayout->addWidget(fir_password,1,0);
uplayout->addWidget(fir_password_line,1,1);
uplayout->addWidget(confirm_password,2,0);
uplayout->addWidget(confirm_password_line,2,1);
QHBoxLayout* downlayout=new QHBoxLayout;
downlayout->addWidget(fin_btn);
downlayout->addWidget(cancel_btn);
QVBoxLayout* alllayout=new QVBoxLayout(this);
alllayout->addLayout(uplayout);
alllayout->addLayout(downlayout);
connect(fin_btn,&QPushButton::clicked,[=](){
if(fir_password_line->text()!=confirm_password_line->text()&&fir_password_line->text()!=nullptr){
QMessageBox::warning(this,"提示","password diff");
}else{
QString ip="192.168.70.90";
unsigned int port=9999;
socket->connectToHost(ip,port);
QString password=confirm_password_line->text();
socket->write(password.toUtf8());
connect(socket,&QTcpSocket::readyRead,[=](){
QString id=socket->readAll();
qDebug()<<id;
QMessageBox::information(this,"提示","Your id:"+id);
cre_name_line->clear();
fir_password_line->clear();
confirm_password_line->clear();
socket->close();
});
emit reg_fin_signals();
}
});
connect(cancel_btn,&QPushButton::clicked,[=](){
emit reg_cancel_signals();
});
}
widget.cpp:
#include "widget.h"
#include <QGridLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMessageBox>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
this->setWindowTitle("my_stu_system");
this->setFixedSize(330,230);
QPalette p = this->palette();
p.setBrush(QPalette::Window,QBrush(QPixmap("D:/UserData/Desktop/pic.png")));
this->setPalette(p);
usrname=new QLabel("id:",this);
password=new QLabel("password:",this);
usrnameline=new QLineEdit(this);
passwordline=new QLineEdit(this);
socket=new QTcpSocket(this);
passwordline->setEchoMode(QLineEdit::Password);
log_btn=new QPushButton("log",this);
reg_btn=new QPushButton("reg",this);
QGridLayout* uplayout=new QGridLayout;
uplayout->addWidget(usrname,0,0);
uplayout->addWidget(usrnameline,0,1);
uplayout->addWidget(password,1,0);
uplayout->addWidget(passwordline,1,1);
QHBoxLayout* downlayout=new QHBoxLayout;
downlayout->addWidget(reg_btn);
downlayout->addWidget(log_btn);
QVBoxLayout* alllayout=new QVBoxLayout(this);
alllayout->addLayout(uplayout);
alllayout->addLayout(downlayout);
reg_dialog=new reg_interface(this);
connect(reg_btn,&QPushButton::clicked,this,&Widget::show_reg_interface);
connect(reg_dialog,®_interface::reg_fin_signals,[=](){
this->show();
reg_dialog->close();
});
connect(reg_dialog,®_interface::reg_cancel_signals,[=](){
this->show();
reg_dialog->close();
});
connect(log_btn,&QPushButton::clicked,this,[=](){
QString ip="192.168.70.90";
unsigned int port=7777;
socket->connectToHost(ip,port);
QString id=usrnameline->text();
QString password="?p="+passwordline->text();
QString info=id+password;
socket->write(info.toUtf8());
usrnameline->clear();
passwordline->clear();
connect(socket,&QTcpSocket::readyRead,[=](){
QString msg=socket->readAll();
qDebug()<<msg;
socket->close();
if(!QString::compare(msg,"OK")){
int id_int=id.toInt();
log_dialog=new log_interface(this);
log_dialog->setid(id_int);
log_dialog->show();
this->hide();
}else if(!QString::compare(msg,"NO")){
QMessageBox::warning(this,"提示"," id or password error");
}
});
});
}
void Widget::show_reg_interface(){
usrnameline->clear();
passwordline->clear();
reg_dialog->show();
this->hide();
}
Widget::~Widget()
{
}
main.cpp:
#include "widget.h"
#include <QApplication>
#include <QSqlQuery>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
QSqlDatabase db=QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("my_stu_system_usrinfo");
db.open();
QSqlQuery query;
query.exec(QObject::tr("create table if not exists info(id int primary key,password char)"));
query.exec(QObject::tr("insert into info values(1000,0)"));
w.show();
return a.exec();
}