用QT編寫基於TCP的網絡通信程序
我編寫的是一個類似實時做題的小程序,不多bb,看演示如下:
算了,還是描述下上圖的操作過程(真香~~)
- 運行服務器端先監聽本地ip爲
127.0.0.1
,端口是8081
(無所謂的) - 運行客戶端,讓它連接上服務器
- 服務器端發送題目到客戶端
- 客戶端就可以開始做題,做完題後,點擊提交
- 服務器端就是收到信息,瞭解到客戶端做題結果
其餘說明:
- 服務器端的題目是寫死在程序中
- 服務器端的日誌框顯示的是所有的日誌情況,包括客戶端和服務器端
操作小記
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());
}
}