欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

QTday7

程序员文章站 2022-03-10 21:49:02
...

day7

  1. —–在线词典—–(用文件保存用户名密码)

dictclient

QTday7

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. —–登录注册使用在线词典—–

QTday7

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";
}
相关标签: QT

推荐阅读