QTday7

day7

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

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

服务端流程图

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";
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值