最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Qt中TCP Socket的實(shí)現(xiàn)

 更新時(shí)間:2026年02月06日 08:52:26   作者:楓葉丹4  
Qt框架通過(guò)QTcpServer和QTcpSocket類提供跨平臺(tái)的TCP通信能力,本文就來(lái)介紹一下Qt中TCP Socket的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1 -> 概述

TCP(Transmission Control Protocol,傳輸控制協(xié)議)是一種面向連接、可靠、基于字節(jié)流的傳輸層通信協(xié)議。在 Qt 框架中,TCP 網(wǎng)絡(luò)編程主要通過(guò) QTcpServerQTcpSocket 兩個(gè)核心類來(lái)實(shí)現(xiàn),它們封裝了底層 Socket 的復(fù)雜性,提供了面向?qū)ο?、事件?qū)動(dòng)的高級(jí) API,大大簡(jiǎn)化了網(wǎng)絡(luò)應(yīng)用的開(kāi)發(fā)過(guò)程。

Qt 的網(wǎng)絡(luò)模塊是跨平臺(tái)的,這意味著使用 Qt 編寫(xiě)的 TCP 程序可以在 Windows、Linux、macOS 等操作系統(tǒng)上運(yùn)行而無(wú)需修改代碼,這對(duì)于需要部署在多種環(huán)境下的應(yīng)用程序來(lái)說(shuō)是一個(gè)巨大的優(yōu)勢(shì)。

在 Qt 中進(jìn)行 TCP 編程,本質(zhì)上是在構(gòu)建客戶端-服務(wù)器模型。服務(wù)器負(fù)責(zé)監(jiān)聽(tīng)指定端口、接受客戶端連接請(qǐng)求并與客戶端進(jìn)行數(shù)據(jù)交換;客戶端則主動(dòng)發(fā)起連接,與服務(wù)器建立通信鏈路并進(jìn)行數(shù)據(jù)傳輸。Qt 的信號(hào)與槽機(jī)制非常適合處理網(wǎng)絡(luò)事件,例如連接建立、數(shù)據(jù)到達(dá)、連接斷開(kāi)等,使得程序邏輯清晰、易于維護(hù)。

2 -> 核心 API 詳解

2.1 -> QTcpServer

QTcpServer 類用于創(chuàng)建一個(gè) TCP 服務(wù)器,其主要職責(zé)是監(jiān)聽(tīng)指定 IP 地址和端口,接受傳入的連接請(qǐng)求,并為每個(gè)連接創(chuàng)建一個(gè)獨(dú)立的 QTcpSocket 對(duì)象來(lái)處理后續(xù)通信。

2.1.1 -> 關(guān)鍵方法

  • bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
    啟動(dòng)服務(wù)器監(jiān)聽(tīng)。

    • address:監(jiān)聽(tīng)的 IP 地址,QHostAddress::Any 表示監(jiān)聽(tīng)所有網(wǎng)絡(luò)接口。
    • port:端口號(hào),如果設(shè)為 0,系統(tǒng)會(huì)自動(dòng)分配一個(gè)可用端口。
    • 返回值:成功監(jiān)聽(tīng)返回 true,否則返回 false(可通過(guò) errorString() 獲取錯(cuò)誤信息)。
  • QTcpSocket *nextPendingConnection()
    獲取下一個(gè)等待處理的客戶端連接。
    該方法返回一個(gè)已建立連接的 QTcpSocket 對(duì)象,該對(duì)象由 QTcpServer 內(nèi)部創(chuàng)建并管理,用于后續(xù)與對(duì)應(yīng)客戶端的數(shù)據(jù)交換。
    注意:每次調(diào)用都應(yīng)檢查返回值是否為 nullptr。

2.1.2 -> 關(guān)鍵信號(hào)

  • void newConnection()
    當(dāng)有新的客戶端連接成功時(shí)觸發(fā)此信號(hào)。通常在此信號(hào)的槽函數(shù)中調(diào)用 nextPendingConnection() 獲取新連接并進(jìn)行初始化設(shè)置(如連接信號(hào)槽、保存 socket 對(duì)象等)。

2.1.3 -> 工作流程簡(jiǎn)述

  1. 創(chuàng)建 QTcpServer 對(duì)象。
  2. 調(diào)用 listen() 綁定端口并開(kāi)始監(jiān)聽(tīng)。
  3. 連接 newConnection() 信號(hào)到自定義槽函數(shù)。
  4. 在槽函數(shù)中通過(guò) nextPendingConnection() 獲取客戶端 socket。
  5. 為獲取到的 socket 連接相關(guān)信號(hào)(如 readyRead、disconnected),實(shí)現(xiàn)業(yè)務(wù)邏輯。

2.2 -> QTcpSocket

QTcpSocket 類代表一個(gè) TCP 連接,既可用于客戶端發(fā)起連接,也可用于服務(wù)器端處理某個(gè)具體客戶端的通信。它繼承自 QAbstractSocket,并間接繼承自 QIODevice,因此可以像文件一樣進(jìn)行讀寫(xiě)操作。

2.2.1 -> 關(guān)鍵方法

  • void connectToHost(const QString &hostName, quint16 port, OpenMode openMode = ReadWrite)
    (客戶端使用)連接到指定的服務(wù)器。

    • hostName:主機(jī)名或 IP 地址。
    • port:目標(biāo)端口。
    • openMode:打開(kāi)模式,通常為 ReadWrite。
  • qint64 read(char *data, qint64 maxSize) / QByteArray readAll() / QByteArray read(qint64 maxSize)
    從接收緩沖區(qū)讀取數(shù)據(jù)。readAll() 會(huì)讀取所有當(dāng)前可用的數(shù)據(jù),返回 QByteArray 對(duì)象。

  • qint64 write(const char *data, qint64 size) / qint64 write(const QByteArray &data)
    向連接中寫(xiě)入數(shù)據(jù)。數(shù)據(jù)會(huì)被放入發(fā)送緩沖區(qū),由 Qt 在后臺(tái)異步發(fā)送。

  • void disconnectFromHost()
    主動(dòng)斷開(kāi)連接。斷開(kāi)過(guò)程是異步的,可配合 disconnected() 信號(hào)使用。

  • void abort()
    立即中止連接,丟棄所有未發(fā)送或未接收的數(shù)據(jù)。

2.2.2 -> 關(guān)鍵信號(hào)

  • void connected()
    成功連接到遠(yuǎn)程主機(jī)后觸發(fā)。

  • void disconnected()
    連接斷開(kāi)時(shí)觸發(fā)(可能是遠(yuǎn)程主機(jī)關(guān)閉、網(wǎng)絡(luò)故障或主動(dòng)斷開(kāi))。

  • void readyRead()
    當(dāng)有新的數(shù)據(jù)到達(dá)并可供讀取時(shí)觸發(fā)。由于 TCP 是流式協(xié)議,數(shù)據(jù)可能分多次到達(dá),通常在此信號(hào)的槽函數(shù)中循環(huán)讀取直到 bytesAvailable() 為 0。

  • void bytesWritten(qint64 bytes)
    當(dāng)部分?jǐn)?shù)據(jù)被成功寫(xiě)入底層 socket 時(shí)觸發(fā),可用于實(shí)現(xiàn)發(fā)送進(jìn)度指示或流量控制。

2.2.3 -> 關(guān)鍵屬性與狀態(tài)

  • state()
    返回 socket 的當(dāng)前狀態(tài)(如 UnconnectedState、ConnectedState 等)。

  • error() 與 errorString()
    獲取最后一次發(fā)生的錯(cuò)誤代碼及描述。

  • peerAddress() 與 peerPort()
    獲取遠(yuǎn)程對(duì)端的 IP 地址和端口號(hào)(在連接建立后有效)。

2.3 -> QByteArray 與 QString 的轉(zhuǎn)換

由于網(wǎng)絡(luò)傳輸?shù)氖亲止?jié)流,而 Qt 程序中常使用 QString 處理文本,因此兩者間的轉(zhuǎn)換非常常見(jiàn):

  • QString → QByteArray
    QString str = "Hello";
    QByteArray data = str.toUtf8(); // 常用 UTF-8 編碼
    
  • QByteArray → QString
    QByteArray data = ...;
    QString str = QString::fromUtf8(data);
    

3 -> 通信流程概述

3.1 -> 服務(wù)器端典型流程

  1. 創(chuàng)建 QTcpServer,監(jiān)聽(tīng)指定端口。
  2. newConnection() 槽中接受新連接,獲取 QTcpSocket
  3. 為該 socket 連接 readyRead() 信號(hào),在槽函數(shù)中讀取請(qǐng)求數(shù)據(jù),處理業(yè)務(wù),并回復(fù)響應(yīng)。
  4. 連接 disconnected() 信號(hào),在客戶端斷開(kāi)時(shí)進(jìn)行資源清理(如調(diào)用 deleteLater() 刪除 socket 對(duì)象)。

3.2 -> 客戶端典型流程

  1. 創(chuàng)建 QTcpSocket,調(diào)用 connectToHost() 連接服務(wù)器。
  2. 連接 connected() 信號(hào),確認(rèn)連接成功。
  3. 連接 readyRead() 信號(hào),接收服務(wù)器返回的數(shù)據(jù)。
  4. 使用 write() 發(fā)送請(qǐng)求數(shù)據(jù)。
  5. 在適當(dāng)時(shí)機(jī)斷開(kāi)連接或處理異常斷開(kāi)。

4 -> 代碼示例

4.1 -> 回顯客戶端

widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include <QMessageBox>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 1. 創(chuàng)建 QTcpServer 的實(shí)例
    socket = new QTcpSocket(this);

    // 2. 設(shè)置標(biāo)題
    this->setWindowTitle("客戶端");

    // 3. 和服務(wù)器建立連接
    socket->connectToHost("127.0.0.1", 9090);

    // 4. 連接信號(hào)槽, 處理響應(yīng)
    connect(socket, &QTcpSocket::readyRead, this, [=](){
        // a) 讀取出響應(yīng)內(nèi)容
        QString response = socket->readAll();

        // b) 把響應(yīng)內(nèi)容顯示到界面上
        ui->listWidget->addItem("服務(wù)器說(shuō): " + response);

    });

    // 5. 等待連接建立的結(jié)果. 確認(rèn)是否連接成功
    bool ret = socket->waitForConnected();
    if (!ret)
    {
        QMessageBox::critical(this, "連接服務(wù)器出錯(cuò)", socket->errorString());
        exit(1);
    }

}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    // 1. 獲取到輸入框中的內(nèi)容
    const QString& text = ui->lineEdit->text();

    // 2. 發(fā)送數(shù)據(jù)給服務(wù)器
    socket->write(text.toUtf8());

    // 3. 把發(fā)的消息顯示到界面上
    ui->listWidget->addItem("客戶端說(shuō): " + text);

    // 4. 清空輸入框的內(nèi)容
    ui->lineEdit->setText("");

}

4.2 -> 回顯服務(wù)端

widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include <QMessageBox>
#include <QTcpSocket>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 1. 創(chuàng)建 QTcpServer 的實(shí)例
    tcpServer = new QTcpServer(this);

    // 2. 設(shè)置標(biāo)題
    this->setWindowTitle("服務(wù)器");

    // 3. 通過(guò)信號(hào)槽, 指定如何處理連接
    connect(tcpServer, &QTcpServer::newConnection, this, &Widget::processConnection);

    bool ret = tcpServer->listen(QHostAddress::Any, 9090);
    if (!ret)
    {
        QMessageBox::critical(this, "服務(wù)器啟動(dòng)失敗!", tcpServer->errorString());
        exit(1);
    }

}

Widget::~Widget()
{
    delete ui;
}

void Widget::processConnection()
{
    // 1. 通過(guò) tcpServer 拿到一個(gè) socket 對(duì)象, 通過(guò)這個(gè)對(duì)象來(lái)和客戶端進(jìn)行通信
    QTcpSocket* clientSocket = tcpServer->nextPendingConnection();
    QString log = "[ " + clientSocket->peerAddress().toString() + ": " + QString::number(clientSocket->peerPort()) +
            " ] 客戶端上線!";
    ui->listWidget->addItem(log);

    // 2. 通過(guò)信號(hào)槽, 來(lái)處理客戶端發(fā)來(lái)請(qǐng)求的情況
    connect(clientSocket, &QTcpSocket::readyRead, this, [=](){
        // a) 讀取出請(qǐng)求數(shù)據(jù). 此處 readAll 返回的是 QByteArray, 通過(guò)賦值轉(zhuǎn)成 QString
        QString request = clientSocket->readAll();

        // b) 根據(jù)請(qǐng)求處理響應(yīng)
        const QString& response = process(request);

        // c) 把響應(yīng)寫(xiě)回到客戶端
        clientSocket->write(response.toUtf8());

        // d) 把上述信息記錄到日志中
        QString log = "[ " + clientSocket->peerAddress().toString() + ": " + QString::number(clientSocket->peerPort()) + " ] "
                + "req: " + request + ", " + "resp: " + response;
        ui->listWidget->addItem(log);

    });

    // 3. 通過(guò)信號(hào)槽, 來(lái)處理客戶端斷開(kāi)連接的情況
    connect(clientSocket, &QTcpSocket::disconnected, this, [=](){
        // a) 把斷開(kāi)連接的信息通過(guò)日志顯示出來(lái)
        QString log = "[ " + clientSocket->peerAddress().toString() + ": " + QString::number(clientSocket->peerPort()) +
                " ] 客戶端下線!";
        ui->listWidget->addItem(log);
        // b) 手動(dòng)釋放 clientSocket. 直接使用 delete 是下策, 使用 deleteLater 更加合適的.
        // delete clientSocket;
        clientSocket->deleteLater();
    });

}

// 此處寫(xiě)的是回顯服務(wù)器
QString Widget::process(const QString request)
{

    return request;
}


5 -> 總結(jié)

Qt 的 TCP 網(wǎng)絡(luò)編程模塊通過(guò) QTcpServerQTcpSocket 提供了高度封裝、易于使用的 API,大大降低了網(wǎng)絡(luò)應(yīng)用程序的開(kāi)發(fā)難度。其特點(diǎn)可總結(jié)如下:

  • 面向?qū)ο笈c事件驅(qū)動(dòng):通過(guò)信號(hào)與槽機(jī)制處理連接、數(shù)據(jù)接收、斷開(kāi)等事件,代碼結(jié)構(gòu)清晰。
  • 跨平臺(tái)性:同一套代碼可在主流操作系統(tǒng)上運(yùn)行,無(wú)需關(guān)心底層 Socket API 差異。
  • 與 Qt 生態(tài)無(wú)縫集成:可方便地與 GUI、多線程、定時(shí)器、文件 IO 等其他 Qt 模塊結(jié)合使用。
  • 高效的異步 IO:基于事件循環(huán),無(wú)需阻塞線程即可處理多個(gè)并發(fā)連接,適合高性能服務(wù)器開(kāi)發(fā)。
  • 良好的錯(cuò)誤處理機(jī)制:提供詳細(xì)的錯(cuò)誤碼和描述,便于調(diào)試和異常處理。

在實(shí)際開(kāi)發(fā)中,除了掌握上述基礎(chǔ) API 外,還需注意資源管理(及時(shí)釋放 socket)、協(xié)議設(shè)計(jì)(定義清晰的數(shù)據(jù)包格式以處理粘包/半包問(wèn)題)、多線程處理(將耗時(shí)操作移至子線程以避免阻塞主循環(huán))等高級(jí)主題。Qt 的網(wǎng)絡(luò)模塊為構(gòu)建穩(wěn)定、高效的 C++ 網(wǎng)絡(luò)應(yīng)用提供了堅(jiān)實(shí)的基礎(chǔ),是開(kāi)發(fā)跨平臺(tái)客戶端/服務(wù)器程序的優(yōu)秀選擇。

到此這篇關(guān)于Qt中TCP Socket的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Qt TCP Socket內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言中計(jì)算二叉樹(shù)的寬度的兩種方式

    C語(yǔ)言中計(jì)算二叉樹(shù)的寬度的兩種方式

    這篇文章主要介紹了C語(yǔ)言中計(jì)算二叉樹(shù)的寬度的兩種方式的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • MFC修改編輯框光標(biāo)顯示位置方法詳解

    MFC修改編輯框光標(biāo)顯示位置方法詳解

    這篇文章主要介紹了在MFC中利用CComboBox控件修改編輯框光標(biāo)顯示位置的兩種解決方法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2022-02-02
  • C語(yǔ)言深入探究棧的原理

    C語(yǔ)言深入探究棧的原理

    一種特殊的線性表,其只允許在固定的一端進(jìn)行插入和刪除元素操作。進(jìn)行數(shù)據(jù)插入和刪除操作的一端 稱為棧頂,另一端稱為棧底。棧中的數(shù)據(jù)元素遵守后進(jìn)先出LIFO(Last In First Out)的原則
    2021-11-11
  • C++ vector類的模擬實(shí)現(xiàn)方法

    C++ vector類的模擬實(shí)現(xiàn)方法

    這篇文章主要介紹了C++ vector類的模擬實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • C語(yǔ)言struct結(jié)構(gòu)體介紹

    C語(yǔ)言struct結(jié)構(gòu)體介紹

    C語(yǔ)言中,結(jié)構(gòu)體類型屬于一種構(gòu)造類型(其他的構(gòu)造類型還有:數(shù)組類型,聯(lián)合類型),下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言結(jié)構(gòu)體(struct)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • C++中各種初始化方式示例詳解

    C++中各種初始化方式示例詳解

    這篇文章主要給大家介紹了關(guān)于C++中各種初始化方式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單電子通訊錄(2)

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單電子通訊錄(2)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單電子通訊錄的第二部分,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • 通過(guò)“回文字算法”復(fù)習(xí)C++語(yǔ)言

    通過(guò)“回文字算法”復(fù)習(xí)C++語(yǔ)言

    這篇文章主要介紹了通過(guò)“回文字算法”復(fù)習(xí)C++語(yǔ)言的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-10-10
  • C++ 類的構(gòu)造函數(shù)詳解及實(shí)例

    C++ 類的構(gòu)造函數(shù)詳解及實(shí)例

    這篇文章主要介紹了C++ 類的構(gòu)造函數(shù)詳解及實(shí)例的相關(guān)資料,學(xué)習(xí)C++ 的朋友對(duì)構(gòu)造函數(shù)肯定不陌生,非常重要的基礎(chǔ)知識(shí),這里就詳細(xì)介紹下,需要的朋友可以參考下
    2016-12-12
  • C語(yǔ)言文件操作中 fgets與fputs 函數(shù)詳解

    C語(yǔ)言文件操作中 fgets與fputs 函數(shù)詳解

    這篇文章主要介紹了C語(yǔ)言文件操作中 fgets與fputs 函數(shù)詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06

最新評(píng)論

梅州市| 敦煌市| 武穴市| 北安市| 筠连县| 道真| 濮阳县| 达州市| 拜城县| 启东市| 长沙市| 特克斯县| 定州市| 喀喇沁旗| 通许县| 卫辉市| 广昌县| 长乐市| 西华县| 连城县| 嘉祥县| 安达市| 疏附县| 潮州市| 新绛县| 龙陵县| 安乡县| 清流县| 肇源县| 深水埗区| 普定县| 沁阳市| 瓦房店市| 秦安县| 太康县| 台东县| 余姚市| 莎车县| 湖州市| 湘乡市| 贵南县|