QTday7
程序员文章站
2022-03-10 21:49:02
...
day7
- —–在线词典—–(用文件保存用户名密码)
dictclient
main.c控制登录对话框loginDialog m和登录后界面Dialog w的展开
loginDialog m;
if(m.exec()==QDialog::Rejected)//当登录对话框accept()时,登录后界面展开
{
return 0;
}
Dialog w;
w.show();
头文件包含、声明登录对话框loginDialog的四个槽函数三个私有成员变量
...
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void sendRequest();
void readResponse();
private:
Ui::loginDialog *ui;
QTcpSocket tcpSocket;
quint16 nextBlockSize;
quint8 mode;
...
熟悉的套路:初始化时连接信号与槽,按下按钮时产生连接信号,逐一实现槽函数
connect(&tcpSocket,SIGNAL(connected()),this,SLOT(sendRequest()));
connect(&tcpSocket,SIGNAL(readyRead()),this,SLOT(readResponse()));
...
void loginDialog::on_pushButton_clicked()
{
tcpSocket.connectToHost("127.0.0.1",7788); //连接服务器
nextBlockSize=0;
//数据包格式为:总大小 用户名大小 L/R 用户名 密码
mode='L';
}
...
void loginDialog::sendRequest()
{
quint16 tmp;
QByteArray buffer;
QDataStream out(&buffer,QIODevice::WriteOnly);
out << quint16(0) <<quint16(1)<< mode<< ui->lineEdit->text();
//得到用户名大小
tmp=quint16(buffer.size()-sizeof(quint16)-5);
//如何定位到流末尾
out<<ui->lineEdit_2->text();
qDebug()<<"我发送的buffer:"<<buffer;
out.device()->seek(0);
//写入总大小,用户名大小
out<<quint16(buffer.size()-sizeof(quint16))<<tmp;
qDebug()<<"我发送的最终包:"<<buffer;
tcpSocket.write(buffer);
}
void loginDialog::readResponse()
{
QDataStream in(&tcpSocket);
if(nextBlockSize==0)
{
if(tcpSocket.bytesAvailable() < sizeof(quint16))
return;
in >> nextBlockSize;
}
if(tcpSocket.bytesAvailable() < nextBlockSize)
{
return;
}
//接收包格式:大小 Q/L 字符串
quint8 type;
QString str;
in >> type >> str;
if(type == quint8('Q'))
{
qDebug()<<"接收到"<<str;
}else if(type == quint8('L'))
{
if(str=="right")
{
accept();
tcpSocket.close();
return;
}else if(str=="error")
{
QMessageBox::information(this,"error","login failed");
}
}
tcpSocket.close();
}
写完登录对话框,登录后的查询界面也大同小异。1声明槽函数和成员变量,2连接信号与槽,3实现槽函数。
//dialog.h
private slots:
void on_pushButton_clicked();
void sendRequest();
void readResponse();
private:
Ui::Dialog *ui;
QTcpSocket tcpSocket;
quint16 nextBlockSize;
//dialog.cpp
connect(&tcpSocket,SIGNAL(connected()),this,SLOT(sendRequest()));
connect(&tcpSocket,SIGNAL(readyRead()),this,SLOT(readResponse()));
////
void Dialog::on_pushButton_clicked()
{
if(ui->lineEdit->text().isEmpty())
{
ui->textBrowser->setText("Input is empty");
return;
}
tcpSocket.connectToHost("127.0.0.1",7788); //连接服务器
nextBlockSize=0;
}
//
void Dialog::sendRequest()
{
//qDebug()<<"ting....";
QByteArray buffer;
QDataStream out(&buffer,QIODevice::WriteOnly);
//注意,必须与服务端解包的格式保持一致
out << quint16(0) << quint16(9)<<quint8('Q') << ui->lineEdit->text();
out.device()->seek(0);
out << quint16(buffer.size()-sizeof(quint16));
tcpSocket.write(buffer);
//qDebug()<<"ques buffer="<<buffer;
}
//
void Dialog::readResponse()
{
QDataStream in(&tcpSocket);
if(nextBlockSize==0)
{
if(tcpSocket.bytesAvailable() < sizeof(quint16))
return;
in >> nextBlockSize;
}
if(tcpSocket.bytesAvailable() < nextBlockSize)
return;
quint8 type;
QString str;
in >> type >> str;
//qDebug()<<"recv str=:"<<str<<endl;
if(type == quint8('Q'))
{
ui->textBrowser->setText(str);
}
tcpSocket.close();
}
dictserver
文件使用绝对路径。
- —–登录注册使用在线词典—–
1声明
...
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
int setkey(QString& str,QString& str2);
QString checkkey(QString& str,QString& str2);
private slots:
void newClient();
void readClient();
private:
Ui::MainWindow *ui;
QTcpServer tcpServer;
quint16 nextBlockSize;
...
2连接
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
tcpServer.listen(QHostAddress::Any,7788);
connect(&tcpServer,SIGNAL(newConnection()),this,SLOT(newClient()));
}
//
void MainWindow::newClient()
{
//qDebug()<<"new client!"<<endl;
QTcpSocket *tcpSocket=tcpServer.nextPendingConnection();
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readClient()));
connect(tcpSocket,SIGNAL(disconnected()),tcpSocket,SLOT(deleteLater()));
nextBlockSize=0;
}
3接收
void MainWindow::readClient()
{
QTcpSocket *tcpSocket=qobject_cast<QTcpSocket*>(sender());
QDataStream inout(tcpSocket);
if(nextBlockSize==0)
{
if(tcpSocket->bytesAvailable() < sizeof(quint16))
return;
inout >> nextBlockSize;
}
if(tcpSocket->bytesAvailable() < nextBlockSize)
{
return;
}
quint16 num;
quint8 type;
QString str,str2;
/*DataStream会自动分隔两个字符串*/
inout>>num>>type;
//num强制转换成字符串?
//qDebug()<<"num="<<QString(num)<<"type="<<type;
if(type==quint8('R'))
{
inout>>str>>str2;
/*
inout>>str;
qDebug()<<"str=:"<<str<<endl;
inout>>str2;
qDebug()<<"str=:"<<str2<<endl;
*/
//如果while(1)包起来,就会一直循环检查注册是否成功
setkey(str,str2);
QByteArray buffer;
QDataStream out(&buffer,QIODevice::WriteOnly);
out << quint16(0) <<quint8('Q')<< "register ok" ;
out.device()->seek(0);
out << quint16(buffer.size()-sizeof(quint16));
tcpSocket->write(buffer);
return;
}
if(type==quint8('L'))
{
inout>>str>>str2;
QString ans;
//登录判断
ans=checkkey(str,str2);
qDebug()<<"ans="<<ans<<endl;
QByteArray buffer;
QDataStream out(&buffer,QIODevice::WriteOnly);
out << quint16(0) <<quint8('L')<< ans;
out.device()->seek(0);
out << quint16(buffer.size()-sizeof(quint16));
tcpSocket->write(buffer);
return;
}
if(type == quint8('Q'))
{
inout>>str;
}
//qDebug()<<"testing str="<<str;
QFile file("F:/myqt/teacher's_code/dictserver/dict.txt");
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
QMessageBox::critical(this,"error","cannot find dict.txt");
return;
}
QTextStream in(&file);
QString line;
while(!in.atEnd())
{
line=in.readLine();
if(line.startsWith(str))
{
str=line.mid(str.length());
str=str.trimmed();
}
}
QByteArray buffer;
QDataStream out(&buffer,QIODevice::WriteOnly);
out << quint16(0) << quint8('Q') << str;
out.device()->seek(0);
out << quint16(buffer.size()-sizeof(quint16));
tcpSocket->write(buffer);
}
4注册和登录时对流操作的公有函数
//注册时写入用户名密码
int MainWindow::setkey(QString &str, QString &str2)
{
QString username = str;
QString password = str2;
QFile file("F:/myqt/teacher's_code/dictserver/password.dat");
//写成了readonly出错,但程序可以运行
if(!file.open(QIODevice::ReadWrite))
{
QMessageBox::warning(this,"error","password.dat open failed");
file.close();
return 0;
}
QDataStream inout(&file);
QString name,word;
//避免出错,每次都读完流里的数据
//读取上一次注册的用户名,判断是否重复注册
while(!inout.atEnd())
{
inout>>name>>word;
if(username==name&&password==word)
{
QMessageBox::warning(this,"error","用户名相同,重复注册");
file.close();
return 0;
}
}
inout<<username<<password;
//qDebug()<<"set name and key:"<<username<<password<<endl;
QMessageBox::information(this,"success","register succesffully");
file.close();
return 1;
}
//登录时判断用户名密码
QString MainWindow::checkkey(QString &str, QString &str2)
{
QString name = str;
QString word = str2;
QFile file("F:/myqt/teacher's_code/dictserver/password.dat");
if(!file.open(QIODevice::ReadWrite))
{
QMessageBox::warning(this,"error","password.dat open failed");
file.close();
return 0;
}
//qDebug()<<"客户端输入的是"<<"name:"<<name<<"word"<<word<<endl;
QDataStream in(&file);
QString username,password;
while(!in.atEnd())
{
in >>username >>password;
//qDebug()<<"username:"<<username<<"password"<<password<<endl;
if(username==name && password==word)
{
file.close();
//登录成功后,登录界面离线,服务器重新创建套接字与查询界面连接
return "right";
}
}
QMessageBox::information(this,"error","login failed");
file.close();
return "error";
}
上一篇: QTday2
推荐阅读