Qt 學習筆記全系列傳送門: Qt 學習筆記 - 第一章 - 快速開始、信號與槽 Qt 學習筆記 - 第二章 - 添加圖片、佈局、界面切換 Qt 學習筆記 - 第三章 - Qt的三駕馬車之一 - 串口編程 + 程式打包成Windows軟體 【本章】Qt 學習筆記 - 第四章 - Qt的三駕馬車之二 ...
目錄Qt 學習筆記全系列傳送門:
1、TCP 通信
1.1 TCP 編程的特點
- 包含伺服器和客戶端
- 使用時需要在工程文件中引入
QT += network
併在使用時導入包 - 需要使用到的類有
- QTcpServer
- QTcpSocket
1.2 TCP 伺服器案例
需要先定義併在構造中初始化
QTcpServer *tcpServer
和QTcpSocket *tcpSocket
:// 這裡傳入 this 時,父對象被刪除時子對象也會被刪除,省去了delete的麻煩 tcpServer = new QTcpServer(this); tcpSocket = new QTcpSocket(this);
-
工程文件
QT += core gui network
-
UI
-
接收框,只讀
-
埠號輸入框和提示文字
-
發送視窗
-
按鈕,打開伺服器、關閉伺服器、發送
-
控制項改名
-
-
邏輯功能
-
監聽:槽函數,點擊打開伺服器時,需要監聽對應埠是否被訪問
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // 新建tcpServer和tcpSocket的對象,成員屬性在頭文件中已定義,細節不表 tcpServer = new QTcpServer(this); tcpSocket = new QTcpSocket(this); } void Widget::on_openBt_clicked() { // 開啟監聽,監聽所有人的連接,參數指定所有人和一個無符號整型埠 tcpServer->listen(QHostAddress::Any, ui->portEdit->text().toUInt()); }
-
接收:包含獲取和展示兩個部分
-
獲取
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); tcpServer = new QTcpServer(this); tcpSocket = new QTcpSocket(this); // 當監測到新的連接產生的信號時,調用槽函數newConnection_Slot() connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection_Slot())); } void Widget::newConnection_Slot() { // 獲取到已經連接的客戶端的Socket tcpSocket = tcpServer->nextPendingConnection(); // 當存在可讀數據時,調用槽函數readyRead_Slot(),用於展示到接收框中 connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot())); }
-
展示到接收框
void Widget::readyRead_Slot() { // 讀取tcpSocket中的內容,使用字元串接收 QString buf = tcpSocket->readAll(); // 將讀取到的信息展示到接收框中 ui->recvEdit->appendPlainText(buf); }
-
-
發送
void Widget::on_sendBt_clicked() { // 需要轉成 char* tcpSocket->write(ui->sendEdit->text().toLocal8Bit().data()); }
-
關閉
void Widget::on_closeBt_clicked() { tcpServer->close(); tcpSocket->close(); }
-
1.3 TCP 客戶端案例
-
工程文件
QT += core gui network
-
UI
-
接收框,只讀
-
埠號輸入框和提示文字、IP地址輸入框和提示文字
-
發送視窗
-
按鈕,打開伺服器、關閉伺服器、發送
-
控制項改名
-
-
邏輯功能
需要先定義併在構造中初始化
QTcpSocket *tcpSocket
:
tcpSocket = new QTcpSocket(this);
-
連接
void Widget::on_openBt_clicked() { // 點擊打開客戶端時,應連接伺服器,取界面上的ip和埠,埠要轉Uint tcpSocket->connectToHost(ui->ipEdit->text(), ui->portEdit->text().toUInt()); // 當監聽到連接成功的信號connected()時,調用槽函數connected_Slot() connect(tcpSocket, SIGNAL(connected()), this, SLOT(connected_Slot())); }
-
接收
void Widget::connected_Slot() { // 當監聽到有東西可讀的信號readyRead()時,調用槽函數 connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot())); } void Widget::readyRead_Slot() { // 讀取tcpSocket中的信息,展示到頁面上 ui->recvEdit->appendPlainText(tcpSocket->readAll()); }
-
發送
void Widget::on_sendBt_clicked() { // 發送時將發送框中的內容轉為 char* 寫入tcpSocket tcpSocket->write(ui->sendEdit->text().toLocal8Bit()); }
-
關閉
void Widget::on_closeBt_clicked() { tcpSocket->close(); }
-
2、UDP 通信
1.1 UDP 編程的特點
-
不分客戶端和伺服器
-
使用時需要在工程文件中引入
QT += network
併在使用時導入包 -
需要使用 QUdpSocket 類
1.2 UDP 客戶端
需要先定義併在構造中初始化
QUdpSocket *udpSocket
:
udpSocket = new QUdpSocket(this);
-
工程文件
QT += core gui network
-
UI
- 接收框,只讀
- 埠號輸入框和提示文字、目標埠號輸入框和提示文字、IP地址輸入框和提示文字
- 發送視窗
- 按鈕,打開伺服器、關閉伺服器、發送
- 控制項改名
-
邏輯功能
-
啟動
void Widget::on_openBt_clicked() { // 將埠號綁定到Socket if (udpSocket->bind(ui->localPortEdit->text().toUInt())) { QMessageBox::information(this, "提示", "成功"); } else { QMessageBox::information(this, "提示", "失敗"); } // 關聯readyRead信號,有可讀信號調用槽函數 connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_slot())); }
-
接收
void Widget::readyRead_slot() { // hasPendingDatagrams()用於判斷是否讀取完,若沒有讀完則返回true while (udpSocket->hasPendingDatagrams()) { QByteArray arr; // 將數組調整為和 udpSocket 中剩下的數據大小一樣 arr.resize(udpSocket->pendingDatagramSize()); // 將udpSocket中的信息讀取到arr中,參數為接收數組和接收的數據長度 udpSocket->readDatagram(arr.data(), arr.size()); // 將信息寫到頁面上 QString buffer = arr.data(); ui->recvEdit->appendPlainText(buffer); } }
-
發送
void Widget::on_sendBt_clicked() { qunit16 port = ui->aimPortEdit->text().toUInt(); QString sendbuffer = ui->sendEdit->text(); QHostAddress addr; addr.setAddress(ui->aimIpEdit->text()); // 發送的內容需要轉成 char* udpSocket->writeDatagram(sendbuffer.toLocal8Bit().data(), sendbuffer.length(), addr, port); }
-
關閉
void Widget::on_closeBt_clicked() { udpSocket->close(); }
-