欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于QT制作一個(gè)TCPServer與TCPClient的通信

 更新時(shí)間:2023年12月26日 08:42:13   作者:澄澈i  
這篇文章主要為大家詳細(xì)介紹了如何基于QT制作一個(gè)TCPServer與TCPClient的通信,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

前言

之前項(xiàng)目上用到了TCP通信,作為TCP的服務(wù)端上位機(jī)與下位機(jī)進(jìn)行控制信號(hào)傳輸。

這篇博客就對(duì)QT中使用TCP通信理一個(gè)簡(jiǎn)單的demo,做一個(gè)簡(jiǎn)單的TCP服務(wù)端和客戶端的通信。

因?yàn)闀r(shí)間有限,這里就闡述一下基本原理和代碼實(shí)現(xiàn),具體的demo參考的是《QT5.9C++開(kāi)發(fā)指南》

具體效果圖如下

1. TCP通信原理和流程闡述

1.1 TCP 通信原理簡(jiǎn)述

TCP通信主要是三次握手和四次揮手,前者是建立連接,后者是斷開(kāi)連接。

上圖是三次握手的一個(gè)基本流程圖:

首先客戶機(jī)向服務(wù)器申請(qǐng)同步,即向服務(wù)器申請(qǐng)連接。

服務(wù)器接收到請(qǐng)求,返回一個(gè)確認(rèn)幀,告訴客戶機(jī)已經(jīng)收到你的請(qǐng)求,同意連接。

客戶機(jī)收到同意請(qǐng)求信息之后,還要告訴服務(wù)器它已經(jīng)收到服務(wù)器的確認(rèn)請(qǐng)求,接下來(lái)可以傳輸數(shù)據(jù)。

上面是一個(gè)簡(jiǎn)單的TCP建立連接的闡述,那么回歸到服務(wù)器端。在QT中,TCP服務(wù)器端使用QTcpServer用于端口監(jiān)聽(tīng)和建立服務(wù)器,服務(wù)器和客戶端之間在建立連接后,通信使用QTcpSocket,套接字Socket進(jìn)行。

1.2 TCP服務(wù)端建立與通信流程

在QT中,使用QTcpServer::listen()函數(shù)開(kāi)始服務(wù)器端監(jiān)聽(tīng),這里可以指定監(jiān)聽(tīng)的IP地址和端口。這個(gè)表示服務(wù)器的IP和端口,監(jiān)聽(tīng)向這個(gè)IP和端口發(fā)起請(qǐng)求的客戶端。

當(dāng)有新的客戶端接入時(shí),QTcpServer內(nèi)部的incomingConnection()函數(shù)會(huì)創(chuàng)建一個(gè)與客戶端連接的QTcpSocket對(duì)象,接著發(fā)射信號(hào)newConnection()。在newConnection()信號(hào)的槽函數(shù)中,可以用nextPendingConnection()接收客戶端的連接,最后使用QTcpSocket與客戶端通信。

1.3 TCP客戶端通信流程

TCP客戶端使用QTcpSocket與TCP服務(wù)器建立連接并通信。

客戶端的QTcpSocket 實(shí)例首先通過(guò) connectToHost()嘗試連接到服務(wù)器,需要指定服務(wù)器的IP 地址和端口。

connectToHost()是異步方式連接服務(wù)器,不會(huì)阻塞程序運(yùn)行,連接后發(fā)射 connected()信號(hào)。

如果需要使用阻塞方式連接服務(wù)器,則使用 waitForConnected()函數(shù)阻塞程序運(yùn)行,直到連接成功或失敗。
例如:

socket->connectToHost("192.168.1.100",1340);
    if(socket->waitForConnected(1000)
        qDebug("Connected!");

客戶端與服務(wù)器建立socket連接后,就可以向緩沖區(qū)寫數(shù)據(jù)或從接收緩沖區(qū)讀取數(shù)據(jù),實(shí)現(xiàn)數(shù)據(jù)的通信。當(dāng)緩沖區(qū)有新數(shù)據(jù)進(jìn)入時(shí),會(huì)發(fā)射readyRead()信號(hào),一般在此信號(hào)的槽函數(shù)里面讀取緩沖區(qū)數(shù)據(jù)。

2. 關(guān)鍵源碼闡述

2.1 服務(wù)端代碼

初始化TCP服務(wù)端,綁定信號(hào)與槽函數(shù)

    QTcpServer *tcpServer; //TCP服務(wù)器
    QTcpSocket *tcpSocket;//TCP通訊的Socket

    tcpServer=new QTcpServer(this);
    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(onNewConnection()));

定義了一個(gè)TcpServer的對(duì)象tcpServer,將獲取的newConnection()信號(hào)綁定到自定義的槽函數(shù)onNewConnection()上。

開(kāi)始監(jiān)聽(tīng),選擇IP和端口號(hào)

void MainWindow::on_actStart_triggered()
{//開(kāi)始監(jiān)聽(tīng)
    QString     IP=ui->comboIP->currentText();//IP地址
    quint16     port=ui->spinPort->value();//端口
    QHostAddress    addr(IP);
    tcpServer->listen(addr,port);//指定ip和端口,這里的IP就是默認(rèn)IP端口也是控件的默認(rèn)值端口
//    tcpServer->listen(QHostAddress::LocalHost,port);// Equivalent to QHostAddress("127.0.0.1").
    ...
    ...
}

下面這個(gè)函數(shù)綁定了一些tcp連接的狀態(tài)信號(hào)和對(duì)應(yīng)的處理函數(shù)。

對(duì)于接收到的tcpServer連接,使用nextPending函數(shù)創(chuàng)建socket進(jìn)行通信。

void MainWindow::onNewConnection()
{
//    ui->plainTextEdit->appendPlainText("有新連接");
    tcpSocket = tcpServer->nextPendingConnection(); //創(chuàng)建socket

    connect(tcpSocket, SIGNAL(connected()),
            this, SLOT(onClientConnected()));
    onClientConnected();//

    connect(tcpSocket, SIGNAL(disconnected()),
            this, SLOT(onClientDisconnected()));

    connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
    onSocketStateChange(tcpSocket->state());

    connect(tcpSocket,SIGNAL(readyRead()),
            this,SLOT(onSocketReadyRead()));
}

服務(wù)端發(fā)送數(shù)據(jù)函數(shù):

void MainWindow::on_btnSend_clicked()
{//發(fā)送一行字符串,以換行符結(jié)束
    QString  msg=ui->editMsg->text();
    ui->plainTextEdit->appendPlainText("[out] "+msg);
    ui->editMsg->clear();
    ui->editMsg->setFocus();

    QByteArray  str=msg.toUtf8();
    str.append('\n');//添加一個(gè)換行符
    tcpSocket->write(str);
}

服務(wù)器讀取數(shù)據(jù)

void MainWindow::onSocketReadyRead()
{//讀取緩沖區(qū)行文本
//    QStringList   lines;
    while(tcpSocket->canReadLine())
        ui->plainTextEdit->appendPlainText("[in] "+tcpSocket->readLine());
//        lines.append(clientConnection->readLine());
}

2.2 客戶端代碼

對(duì)于客戶端來(lái)說(shuō)主要是socket通信

初始化客戶端并綁定信號(hào)

    QTcpSocket  *tcpClient;  //socket
 	tcpClient=new QTcpSocket(this); //創(chuàng)建socket變量
     connect(tcpClient,SIGNAL(connected()),this,SLOT(onConnected()));
    connect(tcpClient,SIGNAL(disconnected()),this,SLOT(onDisconnected()));

    connect(tcpClient,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
    connect(tcpClient,SIGNAL(readyRead()),
            this,SLOT(onSocketReadyRead()));

連接到服務(wù)器

    QString     addr=ui->comboServer->currentText();
    quint16     port=ui->spinPort->value();
    tcpClient->connectToHost(addr,port);

發(fā)送數(shù)據(jù)

void MainWindow::on_btnSend_clicked()
{//發(fā)送數(shù)據(jù)
    QString  msg=ui->editMsg->text();
    ui->plainTextEdit->appendPlainText("[out] "+msg);
    ui->editMsg->clear();
    ui->editMsg->setFocus();

    QByteArray  str=msg.toUtf8();
    str.append('\n');
    tcpClient->write(str);
}

讀取數(shù)據(jù)

void MainWindow::onSocketReadyRead()
{//readyRead()信號(hào)槽函數(shù)
    while(tcpClient->canReadLine())
        ui->plainTextEdit->appendPlainText("[in] "+tcpClient->readLine());
}

以上就是基于QT制作一個(gè)TCPServer與TCPClient的通信的詳細(xì)內(nèi)容,更多關(guān)于QT TCP通信的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語(yǔ)言Iniparser庫(kù)實(shí)現(xiàn)ini文件讀寫

    C語(yǔ)言Iniparser庫(kù)實(shí)現(xiàn)ini文件讀寫

    iniparser是針對(duì)INI文件的解析器。ini文件則是一些系統(tǒng)或者軟件的配置文件。本文就來(lái)介紹一下如何利用Iniparser庫(kù)實(shí)現(xiàn)ini文件讀寫吧
    2023-03-03
  • C++類與對(duì)象深入之靜態(tài)成員與友元及內(nèi)部類詳解

    C++類與對(duì)象深入之靜態(tài)成員與友元及內(nèi)部類詳解

    朋友們好,這篇播客我們繼續(xù)C++的初階學(xué)習(xí),現(xiàn)在對(duì)我們對(duì)C++的靜態(tài)成員,友元,內(nèi)部類知識(shí)點(diǎn)做出總結(jié),整理出來(lái)一篇博客供我們一起復(fù)習(xí)和學(xué)習(xí),如果文章中有理解不當(dāng)?shù)牡胤?還希望朋友們?cè)谠u(píng)論區(qū)指出,我們相互學(xué)習(xí),共同進(jìn)步
    2022-06-06
  • C++中類模板的應(yīng)用你了解多少

    C++中類模板的應(yīng)用你了解多少

    這篇文章主要為大家詳細(xì)介紹了C++中類模板的應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • C++ vector 遍歷的幾種方法

    C++ vector 遍歷的幾種方法

    本文主要介紹了C++ vector 遍歷的幾種方法,對(duì)vector 遍歷有一定的總結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-07-07
  • C語(yǔ)言實(shí)現(xiàn)二叉樹(shù)鏈?zhǔn)浇Y(jié)構(gòu)的示例詳解

    C語(yǔ)言實(shí)現(xiàn)二叉樹(shù)鏈?zhǔn)浇Y(jié)構(gòu)的示例詳解

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)二叉樹(shù)鏈?zhǔn)浇Y(jié)構(gòu)的相關(guān)資料,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語(yǔ)言有一定的幫助,需要的可以參考一下
    2022-11-11
  • C語(yǔ)言實(shí)現(xiàn)靜態(tài)鏈表的方法

    C語(yǔ)言實(shí)現(xiàn)靜態(tài)鏈表的方法

    分享一段代碼,一個(gè)靜態(tài)鏈表的C語(yǔ)言實(shí)現(xiàn),其中包含著一種簡(jiǎn)單的內(nèi)存管理策略:固定大小的鏈?zhǔn)焦芾怼?/div> 2013-03-03
  • VC判斷一個(gè)文件為目錄的方法

    VC判斷一個(gè)文件為目錄的方法

    這篇文章主要介紹了VC判斷一個(gè)文件為目錄的方法,在Windows應(yīng)用程序設(shè)計(jì)中非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-10-10
  • Qt?QDateTime計(jì)算時(shí)間差的實(shí)現(xiàn)示例

    Qt?QDateTime計(jì)算時(shí)間差的實(shí)現(xiàn)示例

    本文主要介紹了Qt?QDateTime計(jì)算時(shí)間差的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • MFC實(shí)現(xiàn)簡(jiǎn)單計(jì)算器

    MFC實(shí)現(xiàn)簡(jiǎn)單計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了MFC實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C語(yǔ)言實(shí)現(xiàn)單詞小助手功能完善版

    C語(yǔ)言實(shí)現(xiàn)單詞小助手功能完善版

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)單詞小助手功能的完善版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10

最新評(píng)論