完整代碼注釋:實現 Qt 的 TCP 客戶端,實現和服務器通信

一、實驗效果演示

實現 Qt 的 TCP 客戶端,實現和服務器通信

二、代碼框架

三、代碼

tcpclient客戶端代碼

tcpclient.cpp

#include "tcpclient.h"
#include "ui_tcpclient.h"
#include <QDebug>
#include <QMessageBox>
#include <QRegExpValidator>// 構造函數:初始化TCP客戶端界面和成員變量
tcpclient::tcpclient(QWidget *parent): QWidget(parent)                  // 調用父類QWidget的構造函數, ui(new Ui::tcpclient)            // 初始化UI對象, mSocket(nullptr)                 // 初始化TCP套接字指針為nullptr
{ui->setupUi(this);                 // 初始化UI界面setWindowTitle("TCP Client");      // 設置窗口標題為"TCP Client"// 初始狀態下禁用發送功能(未連接服務器時不能發送數據)ui->lineEdit_send->setEnabled(false);  // 禁用發送內容輸入框ui->pushButton_send->setEnabled(false); // 禁用發送按鈕// 設置IP地址驗證器,確保輸入的IP地址格式正確// 創建正則表達式驗證器,用于驗證IPv4地址格式QRegExpValidator *ipValidator = new QRegExpValidator(// 正則表達式:匹配xxx.xxx.xxx.xxx格式的IPv4地址,每個xxx為0-255QRegExp("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"),this  // 父對象為當前窗口,確保內存自動管理);ui->lineEdit_ip->setValidator(ipValidator);  // 為IP輸入框設置驗證器ui->lineEdit_ip->setText("192.168.53.128");  // 設置默認IP地址
}// 析構函數:釋放資源
tcpclient::~tcpclient()
{// 如果套接字存在且處于連接狀態,斷開與服務器的連接if (mSocket && mSocket->state() == QAbstractSocket::ConnectedState) {mSocket->disconnectFromHost();}delete ui;  // 釋放UI對象
}// "連接/斷開"按鈕點擊事件處理函數
void tcpclient::on_pushButton_connect_clicked()
{// 如果套接字未初始化,創建QTcpSocket對象if (!mSocket) {mSocket = new QTcpSocket(this);  // 創建TCP套接字,父對象為當前窗口// 連接信號與槽函數,處理各種網絡事件// 當連接成功建立時,觸發onConnected函數connect(mSocket, &QTcpSocket::connected, this, &tcpclient::onConnected);// 當連接斷開時,觸發onDisconnected函數connect(mSocket, &QTcpSocket::disconnected, this, &tcpclient::onDisconnected);// 當有數據可讀時,觸發onReadyRead函數connect(mSocket, &QTcpSocket::readyRead, this, &tcpclient::onReadyRead);// 當發生錯誤時,觸發onErrorOccurred函數(兼容舊版本Qt)connect(mSocket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &tcpclient::onErrorOccurred);    }// 檢查當前連接狀態if (mSocket->state() == QAbstractSocket::ConnectedState) {// 如果已連接,則斷開連接mSocket->disconnectFromHost();} else {// 未連接狀態,嘗試連接到服務器QString ip = ui->lineEdit_ip->text();       // 獲取輸入的IP地址quint16 port = ui->spinBox_port->value();   // 獲取輸入的端口號// 檢查IP地址是否為空if (ip.isEmpty()) {QMessageBox::warning(this, "警告", "請輸入服務器IP地址");  // 彈出警告對話框return;  // 退出函數,不執行連接操作}// 連接到指定的IP地址和端口號mSocket->connectToHost(QHostAddress(ip), port);// 在消息顯示區添加連接狀態信息ui->textBrowser->insertPlainText("正在連接到 " + ip + ":" + QString::number(port) + "...\n");}
}// "發送"按鈕點擊事件處理函數
void tcpclient::on_pushButton_send_clicked()
{// 檢查套接字是否存在且處于連接狀態if (!mSocket || mSocket->state() != QAbstractSocket::ConnectedState) {return;  // 不滿足條件則退出函數}// 獲取要發送的數據QString str = ui->lineEdit_send->text();// 檢查輸入內容是否為空if (str.isEmpty()) {return;  // 內容為空則不發送}// 發送數據:將QString轉換為UTF-8編碼的字節數組mSocket->write(str.toUtf8());// 在界面上顯示發送的內容,前綴"snd:"標識為發送的數據ui->textBrowser->insertPlainText("snd: " + str + "\n");// 清空發送輸入框ui->lineEdit_send->clear();
}// 連接成功建立時的處理函數
void tcpclient::onConnected()
{// 在消息顯示區添加連接成功信息ui->textBrowser->insertPlainText("已連接到服務器\n");// 將"連接"按鈕文本改為"斷開連接"ui->pushButton_connect->setText("斷開連接");// 啟用發送功能(連接成功后才能發送數據)ui->lineEdit_send->setEnabled(true);  // 啟用發送內容輸入框ui->pushButton_send->setEnabled(true); // 啟用發送按鈕// 禁用IP和端口編輯(連接建立后不允許修改連接參數)ui->lineEdit_ip->setEnabled(false);    // 禁用IP輸入框ui->spinBox_port->setEnabled(false);   // 禁用端口選擇框
}// 連接斷開時的處理函數
void tcpclient::onDisconnected()
{// 在消息顯示區添加斷開連接信息ui->textBrowser->insertPlainText("已與服務器斷開連接\n");// 將"斷開連接"按鈕文本改回"連接"ui->pushButton_connect->setText("連接");// 禁用發送功能(斷開連接后不能發送數據)ui->lineEdit_send->setEnabled(false);  // 禁用發送內容輸入框ui->pushButton_send->setEnabled(false); // 禁用發送按鈕// 啟用IP和端口編輯(斷開連接后允許修改連接參數)ui->lineEdit_ip->setEnabled(true);     // 啟用IP輸入框ui->spinBox_port->setEnabled(true);    // 啟用端口選擇框
}// 有數據可讀時的處理函數
void tcpclient::onReadyRead()
{// 檢查套接字是否存在if (!mSocket) {return;  // 套接字不存在則退出}// 讀取所有接收到的數據QByteArray data = mSocket->readAll();// 在界面上顯示接收的內容,前綴"rcv:"標識為接收的數據ui->textBrowser->insertPlainText("rcv: " + QString(data) + "\n");
}// 網絡錯誤發生時的處理函數
void tcpclient::onErrorOccurred(QAbstractSocket::SocketError error)
{Q_UNUSED(error);  // 標記error參數未使用,避免編譯警告// 檢查套接字是否存在if (mSocket) {// 在消息顯示區添加錯誤信息ui->textBrowser->insertPlainText("錯誤: " + mSocket->errorString() + "\n");}
}

tcpclient.h

#ifndef TCPCLIENT_H  // 防止頭文件被重復包含的宏定義
#define TCPCLIENT_H  // 定義頭文件宏#include <QWidget>       // 包含QWidget類,tcpclient類繼承自QWidget
#include <QTcpSocket>    // 包含QTcpSocket類,用于TCP通信
#include <QAbstractSocket> // 包含QAbstractSocket類,提供套接字的基本功能和枚舉
#include <QRegExpValidator> // 包含QRegExpValidator類,用于正則表達式驗證
#include <QMessageBox>   // 包含QMessageBox類,用于顯示消息對話框
#include <QHostAddress>  // 包含QHostAddress類,用于處理IP地址QT_BEGIN_NAMESPACE  // Qt命名空間開始
namespace Ui { class tcpclient; }  // 聲明Ui命名空間中的tcpclient類(由.ui文件生成)
QT_END_NAMESPACE    // Qt命名空間結束// 定義tcpclient類,繼承自QWidget,用于實現TCP客戶端功能
class tcpclient : public QWidget
{Q_OBJECT  // 啟用Qt的元對象系統,支持信號和槽機制public:// 構造函數:創建tcpclient對象,parent為父窗口指針,默認為nullptrtcpclient(QWidget *parent = nullptr);// 析構函數:釋放tcpclient對象占用的資源~tcpclient();private slots:  // 私有槽函數,用于處理各種事件// 處理"連接/斷開"按鈕的點擊事件void on_pushButton_connect_clicked();// 處理"發送"按鈕的點擊事件void on_pushButton_send_clicked();// 處理連接成功建立的事件void onConnected();// 處理連接斷開的事件void onDisconnected();// 處理有數據可讀的事件void onReadyRead();// 處理網絡錯誤發生的事件,參數為錯誤類型void onErrorOccurred(QAbstractSocket::SocketError error);private:  // 私有成員變量Ui::tcpclient *ui;  // 指向UI界面對象的指針,用于訪問界面控件QTcpSocket *mSocket; // 指向QTcpSocket對象的指針,用于TCP通信
};#endif // TCPCLIENT_H  // 結束頭文件宏定義

tcpclient.pro

QT       += core gui
QT += network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0SOURCES += \main.cpp \tcpclient.cppHEADERS += \tcpclient.hFORMS += \tcpclient.ui# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

main.cpp

#include "tcpclient.h"  // 包含tcpclient類的頭文件,用于創建客戶端窗口對象#include <QApplication>  // 包含QApplication類的頭文件,Qt應用程序的核心類// 程序入口函數,argc是命令行參數數量,argv是命令行參數數組
int main(int argc, char *argv[])
{// 創建QApplication對象a,初始化Qt應用程序,處理命令行參數QApplication a(argc, argv);// 創建tcpclient類的實例w,這是客戶端的主窗口對象tcpclient w;// 顯示主窗口w,此時窗口才會在屏幕上可見w.show();// 進入Qt應用程序的事件循環,等待用戶交互(如點擊按鈕、輸入文本等)// 函數返回應用程序退出時的狀態碼return a.exec();
}

tcpclient.ui(8個組件)

  1. QT設計師界面UI 設計建議:
    客戶端 UI 應包含以下元素:

    • IP 地址輸入框(lineEdit_ip)
    • 端口號選擇框(spinBox_port)
    • 連接 / 斷開按鈕(pushButton_connect)
    • 發送內容輸入框(lineEdit_send)
    • 發送按鈕(pushButton_send)
    • 消息顯示區域(textBrowser)


6TcpServer服務器端

tcpsever.cpp

#include "tcpserver.h"
#include "ui_tcpserver.h"
#include <QDebug>TcpServer::TcpServer(QWidget *parent): QWidget(parent), ui(new Ui::TcpServer)
{ui->setupUi(this);
}TcpServer::~TcpServer()
{delete ui;
}void TcpServer::on_pushButton_start_clicked()
{//1.構建QTcpServer對象mServer = new QTcpServer(this);//連接有客戶端連接上來的信號QObject::connect(mServer,&QTcpServer::newConnection,this,[&](){//獲取客戶端連接上來的套接字mSocket = mServer->nextPendingConnection();//獲取客戶端的地址QHostAddress addr = mSocket->peerAddress();qDebug()<<addr.toString()<<"連接上來!";//使能發送ui->lineEdit->setEnabled(true);ui->pushButton_send->setEnabled(true);//連接readyRead信號和槽QObject::connect(mSocket,&QTcpSocket::readyRead,this,[&](){//接收數據QByteArray arr = mSocket->readAll();//轉換成字符串并顯示QString str(arr);//顯示ui->textBrowser->insertPlainText("rcv:"+str+"\n");});});//2.監聽mServer->listen(QHostAddress::Any,ui->spinBox->value());//禁止修改ui->spinBox->setEnabled(false);ui->pushButton_start->setEnabled(false);
}//發送
void TcpServer::on_pushButton_send_clicked()
{//獲取發送的數據QString str = ui->lineEdit->text();//轉換成QByteArrayQByteArray arr;arr.append(str);//發送mSocket->write(arr);//顯示要發送的內容ui->textBrowser->insertPlainText("snd:"+str+"\n");//清空ui->lineEdit->clear();
}

main.cpp

#include "tcpserver.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);TcpServer w;w.show();return a.exec();
}

tcpserver.h

#ifndef TCPSERVER_H
#define TCPSERVER_H#include <QWidget>
#include <QtNetwork>QT_BEGIN_NAMESPACE
namespace Ui { class TcpServer; }
QT_END_NAMESPACEclass TcpServer : public QWidget
{Q_OBJECTpublic:TcpServer(QWidget *parent = nullptr);~TcpServer();private slots:void on_pushButton_start_clicked();void on_pushButton_send_clicked();private:Ui::TcpServer *ui;//TCP服務器QTcpServer *mServer;QTcpSocket *mSocket;
};
#endif // TCPSERVER_H

6TcpServer.pro

QT       += core gui networkgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0SOURCES += \main.cpp \tcpserver.cppHEADERS += \tcpserver.hFORMS += \tcpserver.ui# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

tcpserver.ui(6個組件)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/94810.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/94810.shtml
英文地址,請注明出處:http://en.pswp.cn/web/94810.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AR培訓系統:油氣行業的安全與效率革新

在油氣行業&#xff0c;一場由增強現實&#xff08;AR www.teamhelper.cn &#xff09;技術引領的培訓革命正在悄然發生。新員工們不再需要冒著生命危險在真實的鉆井平臺上學習操作&#xff0c;而是通過AR眼鏡在虛擬環境中模擬鉆井、起下鉆甚至處理井噴等復雜操作。這種創新的培…

Linux 多線程:互斥與同步

Linux 多線程中的互斥與同步 —— pthread_mutex 與 semaphore在 Linux 多線程編程中&#xff0c;線程間共享全局變量或數據結構是常見場景。如果多個線程同時讀寫同一塊內存&#xff0c;就可能產生 數據競爭 和 不一致。為了解決這些問題&#xff0c;Linux 提供了多種 線程同步…

技術演進中的開發沉思-81 Linux系列:進程地址空間

上一個篇幅和大家聊了進程地址空間、內存描述符這些 Linux 內存管理的 “基本功”&#xff0c;我的一些學生問&#xff1a;“這些概念聽起來簡單&#xff0c;可實際開發中怎么用得上&#xff1f;” 我想今天把這些 “理論骨架” 填上 “實踐血肉”—— 畢竟我當年踩過的坑、摸過…

【聯通分量】題解:P13823 「Diligent-OI R2 C」所謂伊人_連通分量_最短路_01bfs_圖論_C++算法競賽

洛谷博客&#xff1a;https://www.luogu.com.cn/article/5n200x7y Link - P13823 討論區中有很多有用的 hack&#xff0c;沒過的話可以去看看。 每個點都可以換到其所在弱連通分量的最大點權&#xff0c;這是毋庸置疑的。 為了方便陳述&#xff0c;下文中記當前弱連通分量中…

區塊鏈+隱私計算護航“東數西算”數據安全報告

一、背景與政策支持1.1 "東數西算"工程概況戰略定位&#xff1a;作為數字經濟時代的核心"底座"&#xff0c;"東數西算"工程是國家級算力資源跨域調配戰略工程&#xff0c;旨在構建全國一體化算力網絡體系。啟動時間與布局&#xff1a;2022年2月&…

STM32——PWR

一、PWR1.1PWR簡介PWR&#xff08;Power Control&#xff09;電源控制PWR負責管理STM32內部的電源供電部分&#xff0c;可以實現可編程電壓監測器和低功耗模式的功能可編程電壓監測器&#xff08;PVD&#xff09;可以監控VDD電源電壓&#xff0c;當VDD下降到PVD閥值以下或上升到…

Linux系統網絡管理學習.2

目錄 一、學習目標與適用場景 二、網絡管理基礎概念 1. NetworkManager服務 2. 核心管理工具 三、NetworkManager服務管理&#xff08;基礎操作&#xff09; 1. 服務狀態控制 四、網絡參數配置&#xff08;IP/DNS/網關&#xff09; 1. 圖形化配置&#xff08;僅了解&…

響應式編程之Flow框架

文章目錄一、技術背景與產生原因1.1 響應式編程的興起1.2 響應式流規范&#xff08;Reactive Streams&#xff09;1.3 解決的問題1.4 響應式編程二、Flow API核心組件2.1 核心概念2.2 接口關系圖2.2 接口詳解2.3 背壓機制三、完整示例3.1 入門示例3.2 基礎發布-訂閱示例3.3 帶背…

ABeam中國 | 中國汽車市場(5)——軟件定義汽車(SDV)的智能化應用場景

前言本系列前四篇深入探討了中國新能源汽車市場的崛起與電動化進程中的挑戰。本文聚焦軟件定義汽車&#xff08;SDV&#xff09;的三大核心應用場景 ——高級駕駛輔助系統&#xff08;ADAS&#xff09;、智能駕駛艙人機界面&#xff08;HMI&#xff09;及出行即服務&#xff08…

BugKu Web滲透之成績查詢

打開網頁&#xff0c;頁面如下&#xff1a;輸入框中輸入不同的數字可以查詢不同的結果。輸入1后點擊submit按鈕&#xff0c;下方出現成績結果。從題目上看感覺是一個SQL注入的漏洞。思路有下&#xff1a;1.自己手動拼接一些常見的SQL注入。2.用bp抓包后用SQLMap去跑。首先&…

【MES】工業4.0智能制造數字化工廠(數字車間、MES、ERP)解決方案:智能工廠體系架構、系統集成以及智能設計、生產、管理、倉儲物流等

工業4.0智能制造數字化工廠的解決方案&#xff0c;涵蓋了智能制造的背景、企業實現智能工廠的好處、智能工廠的規劃與實現方法以及系統實施模塊的詳細介紹。通過上汽通用凱迪拉克工廠的案例展示了智能工廠的強大能力&#xff0c;強調了數據、技術、管理、人員等關鍵要素在智能制…

3.【鴻蒙應用開發實戰: 從入門到精通】開發入門 Hello World

1.【鴻蒙應用開發實戰: 從入門到精通】開發入門 Hello World1.1 前言1.2 創建一個新項目1.2.1 打開DevEco Studio1.2.2 點擊 Create Project 創建項目1.3 遺留問題1.4 總結與開發建議1.5 結束語1.1 前言 上篇博文【2.【鴻蒙應用開發實戰: 從入門到精通】開發環境搭建】我們已經…

mac系統本地部署Dify步驟梳理

更換終端&#xff0c;適配步驟梳理見筆記前提&#xff1a;已安裝docker desktop&#xff0c;若未安裝&#xff0c;跳轉至文末先安裝1.Git軟件準備&#xff08;1&#xff09;確認查詢Git版本&#xff08;2&#xff09;如果查詢不到系統會提示安裝&#xff0c;點擊安裝即可&#…

深度學習——基于卷積神經網絡實現食物圖像分類【1】(datalodar處理方法)

1. 項目概述 在這個項目中&#xff0c;我們將使用PyTorch框架構建一個卷積神經網絡(CNN)來實現食物圖像分類任務。我們的數據集包含20種不同的食物類別&#xff0c;包括八寶粥、巴旦木、白蘿卜、板栗等常見食物。本文將詳細介紹從數據準備、模型構建到訓練和評估的完整流程。 …

華中科大聯手小米推出ReCogDrive:自動駕駛迎來“認知革命”!

1.【前言】 在開放道路中實現安全、平穩、泛化的自動駕駛&#xff0c;是智能交通領域的“圣杯”。盡管近年來 端到端自動駕駛&#xff08;End-to-End Autonomous Driving, E2E-AD&#xff09; 框架&#xff08;如 UniAD、VAD&#xff09;在 NuScenes 等基準中展現出優異表現&a…

基于 Spring AMQP 的 RabbitMQ 分布式消息系統實戰

在分布式系統中&#xff0c;服務間的解耦與異步通信是關鍵挑戰。RabbitMQ 作為一款成熟的消息中間件&#xff0c;憑借其靈活的交換器模型&#xff08;Direct/Fanout/Topic&#xff09;、可靠的消息傳遞機制&#xff08;持久化、確認機制&#xff09;和豐富的客戶端支持&#xf…

計算機網絡:天氣預報

一、預期結果程序運行輸入所要查詢的地點&#xff0c;然后出現三個選項實時天氣、未來天氣、生活指數。二、實現思路&#xff08;一&#xff09;Ubuntu中利用NOWapi服務器獲取訪問數據api地址&#xff0c;然后創建客戶端利用TCP、IPV4協議分別訪問實時天氣&#xff0c;未來天氣…

GD32VW553-IOT OLED移植

1.前言 本來想用他自身的硬件I2C實現的&#xff0c;但是不知道為啥跑demo一點波形都沒有&#xff0c;改成推挽也沒有波形&#xff0c;只有初始化的電平變化&#xff0c;而且I2C的驅動庫好像有點復雜&#xff0c;起始信號結束信號都得單獨發的&#xff0c;沒有一個全部封裝好的庫…

刀客doc:Instagram會成為Meta廣告業務的第二曲線嗎?

文/刀客doc(頭條深一度精選作者)一如果現在還用“Facebook的小弟”來定義Instagram&#xff0c;多少顯得有些過時了。在和一些出海品牌負責人聊天時&#xff0c;我有個很明顯的感受&#xff1a;他們已經不會再把Instagram當成“附屬資源”去看待。到2025年第二季度&#xff0c;…

Python日期計算完全指南:從上周五到任意日期的高效計算

引言&#xff1a;日期計算的核心價值在業務系統開發中&#xff0c;日期計算是高頻且關鍵的需求。根據2024年企業系統調查報告&#xff1a;85%的財務系統需要計算上周五&#xff08;工資結算日&#xff09;78%的報表系統依賴周數據統計92%的供應鏈系統使用工作日計算65%的BI工具…