Qt課程設計

用QT編寫基於TCP的網絡通信程序

我編寫的是一個類似實時做題的小程序,不多bb,看演示如下:在這裏插入圖片描述
算了,還是描述下上圖的操作過程(真香~~)

  • 運行服務器端先監聽本地ip爲127.0.0.1,端口是8081(無所謂的)
  • 運行客戶端,讓它連接上服務器
  • 服務器端發送題目到客戶端
  • 客戶端就可以開始做題,做完題後,點擊提交
  • 服務器端就是收到信息,瞭解到客戶端做題結果

其餘說明:

  1. 服務器端的題目是寫死在程序中
  2. 服務器端的日誌框顯示的是所有的日誌情況,包括客戶端和服務器端

操作小記

Qt使用網絡通信環境配置

//.pro文件中引入
QT       += network

//引入相關頭文件
//client
#include <QTcpSocket>
#include <QHostAddress>
//server
#include <QTcpServer>
#include <QTcpSocket>
#include <QNetworkInterface>

客戶端編寫

連接服務器
void Widget::on_connectServer_clicked()
{
    QString ipAddr = ui->ipAddr->text();
    quint16 port = ui->port->text().toUShort();
    client->connectToHost(ipAddr, port);

    qDebug()<<"connecting server...";

    if(client->waitForConnected(1000))
    {
        qDebug()<<"connect server success";
        QMessageBox::information(NULL, "提示", "連接成功", QMessageBox::Ok);
        ui->disconnectServer->setEnabled(true);
        ui->connectServer->setEnabled(false);
    }
    else
    {
        QMessageBox::critical(NULL, "提示", "連接失敗,請檢查ip地址和端口號", QMessageBox::Ok);
    }
}
斷開服務器
void Widget::on_disconnectServer_clicked()
{
    client->disconnectFromHost();

    qDebug()<<"disconnecting server...";

    if(client->state() == QAbstractSocket::UnconnectedState
            || client->waitForDisconnected(1000))
    {
        qDebug()<<"disconnect server success";
        QMessageBox::information(NULL, "提示", "斷開成功", QMessageBox::Ok);
        ui->disconnectServer->setEnabled(false);
        ui->connectServer->setEnabled(true);
    }
    else
    {
        QMessageBox::critical(NULL, "提示", "斷開失敗,請重試", QMessageBox::Ok);
    }
}
接收數據
void Widget::receiveData()
{
    qDebug()<<"receiveData()";
    QByteArray buffer = client->readAll();
    if(!buffer.isEmpty())
    {
        data = QTextCodec::codecForName("UTF-8")->toUnicode(buffer);
        qDebug()<<data;
    }
    QStringList datas = data.split(",");

    //填充數據到對應控件
    ui->content->setText(datas.at(0));
    ui->buttonA->setText("選項A "+ datas.at(2));
    ui->buttonB->setText("選項B "+ datas.at(3));
    ui->buttonC->setText("選項C "+ datas.at(4));
    ui->buttonD->setText("選項D "+ datas.at(5));
}
發送數據
void Widget::on_commit_clicked()
{
    //對應關係:A-0 B-1 C-2 D-3
    QString clientChoice;

    switch (optionGroup->checkedId())
    {
    case 0:
        clientChoice = "A";
        break;
    case 1:
        clientChoice = "B";
        break;
    case 2:
        clientChoice = "C";
        break;
    case 3:
        clientChoice = "D";
        break;
    }

    if(clientChoice == data.split(",")[1])
    {
        clientChoice.append(",答案正確");
        QMessageBox::information(NULL, "提示", "回答正確(●'◡'●)", QMessageBox::Ok);
    }
    else
    {
        clientChoice.append(",答案錯誤");
        QMessageBox::information(NULL, "提示", "回答錯誤( ▼-▼ )", QMessageBox::Ok);
    }

    qDebug()<<"commit data to server: "<<clientChoice.toUtf8();

    client->write(clientChoice.toUtf8());
}

服務器編寫

獲取所有連接的客戶端
void Widget::connectingClient()
{
    client = server->nextPendingConnection(); //獲取連接過來的客戶端信息
    clients.append(client); //添加入客戶端列表
    ui->journal->append("客戶端("+client->peerAddress().toString().split("::ffff:")[1]+":"+QString::number(client->peerPort())+") 連接服務器");

    //綁定槽函數
    connect(client, SIGNAL(readyRead()), this, SLOT(receiveData()));
    connect(client, SIGNAL(disconnected()), this, SLOT(disconnectedClient()));
}
斷開所有的客戶端
void Widget::disconnectedClient()
{
    //由於disconnected信號並未提供SocketDescriptor,所以需要遍歷尋找
    for(int i=0; i<clients.length(); i++)
    {
        if(clients[i]->state() == QAbstractSocket::UnconnectedState)
        {
            //刪除記錄
            ui->journal->append("客戶端("+clients[i]->peerAddress().toString().split("::ffff:")[1]+":"+QString::number(clients[i]->peerPort())+") 斷開連接");
            clients[i]->destroyed();
            clients.removeAt(i);
        }
    }
}
接收數據
void Widget::receiveData()
{
    qDebug()<<"receiveData()";

    for(int i=0; i<clients.length(); i++)
    {
        QByteArray buffer = clients[i]->readAll();
        if(buffer.isEmpty()) continue;

        QString data = QTextCodec::codecForName("UTF-8")->toUnicode(buffer);
        QStringList datas = data.split(",");

        QString message = tr("客戶端(%1:%2):所選答案爲:%3,%4").arg(clients[i]->peerAddress().toString().split("::ffff:")[1])
                                             .arg(clients[i]->peerPort()).arg(datas.at(0)).arg(datas.at(1));
        ui->journal->append(message);
    }
}
發送數據
void Widget::on_sendData_clicked()
{
    qDebug()<<"sendData(),selected:"<<ui->questionList->currentRow();

    int questionId = ui->questionList->currentRow();

    if(questionId>=0&&questionId<=3)
    {
        targetQuestion = questionList[questionId];
        QMessageBox::information(NULL, "提示", "發送題目成功", QMessageBox::Ok);
    }
    else
    {
        QMessageBox::information(NULL, "提示", "請選擇題目", QMessageBox::Ok);
    }

    qDebug()<<"question data: "+targetQuestion->getStr();

    for(int i=0; i<clients.length(); i++)
    {
        ui->journal->append("客戶端("+clients[i]->peerAddress().toString()+":"+QString::number(clients[i]->peerPort())+")發送習題"+
                            QString::number(questionId));
        clients[i]->write(targetQuestion->getStr().toUtf8());
    }

}
發佈了116 篇原創文章 · 獲贊 58 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章