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

Qt實(shí)現(xiàn)UDP通信的示例代碼

 更新時(shí)間:2022年11月30日 08:36:57   作者:音視頻開(kāi)發(fā)老舅  
UDP是一個(gè)輕量級(jí)、不可靠、面向數(shù)據(jù)報(bào)的、無(wú)連接的傳輸層協(xié)議,多用于可靠性要求不嚴(yán)格,不是非常重要的傳輸,如直播、視頻會(huì)議等等。本文將通過(guò)Qt實(shí)現(xiàn)UDP通信,感興趣的可以了解一下

設(shè)想有如下場(chǎng)景:若干的客戶端與服務(wù)器端建立連接,建立連接后,服務(wù)器端隨機(jī)發(fā)送字符串給客戶端,客戶端打印輸出。該節(jié)案例使用TCP編程。

服務(wù)器端-單線程

頭文件

#pragma once
//
//tcp服務(wù)端-單線程處理客戶端連接
#include <QAbstractSocket>
#include <QObject>
 
class QTcpServer;
class SimpleTcpSocketServerDemo : public QObject
{ 
   
    Q_OBJECT
 
public:
    SimpleTcpSocketServerDemo();
 
private slots:
    void sendData();
    void displayError(QAbstractSocket::SocketError socketError);
 
private:
    QStringList m_oData;
    QTcpServer *m_pTcpServer;
};
 
void testSimpleTcpSocketServerDemo();

源文件

#include "SimpleTcpSocketServerDemo.h"
#include <assert.h>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
#include <QDataStream>
SimpleTcpSocketServerDemo::SimpleTcpSocketServerDemo()
{ 
 
//初始換原始數(shù)據(jù)
m_oData << tr("You've been leading a dog's life. Stay off the furniture.")
<< tr("You've got to think about tomorrow.")
<< tr("You will be surprised by a loud noise.")
<< tr("You will feel hungry again in another hour.")
<< tr("You might have mail.")
<< tr("You cannot kill time without injuring eternity.")
<< tr("Computers are not intelligent. They only think they are.");
//1. 創(chuàng)建TCP對(duì)象
m_pTcpServer = new QTcpServer(this);
//2. 新連接、錯(cuò)誤信號(hào)
connect(m_pTcpServer, &QTcpServer::newConnection, this, &SimpleTcpSocketServerDemo::sendData);
connect(m_pTcpServer, &QTcpServer::acceptError, this, &SimpleTcpSocketServerDemo::displayError);
//3. 啟動(dòng)服務(wù)端
if (!m_pTcpServer->listen(QHostAddress::Any, 8888))
{ 
 
qDebug() << "m_pTcpServer->listen() error";
assert(false);
}
}
void SimpleTcpSocketServerDemo::sendData()
{ 
 
//獲取服務(wù)端數(shù)據(jù)
QString sWriteData = m_oData.at(qrand() % m_oData.size());
//獲取與客戶端通信的socket
QTcpSocket* pClientConnection = m_pTcpServer->nextPendingConnection();
//從客戶端讀數(shù)據(jù)
QString sReadData = pClientConnection->readAll();
qDebug() << "SimpleTcpSocketServerDemo::readDataFromClient " << pClientConnection;
//與客戶端寫數(shù)據(jù)
qDebug() << "SimpleTcpSocketServerDemo::writeDataToClient " << sWriteData;
pClientConnection->write(sWriteData.toUtf8());
// //與客戶端斷開(kāi)連接
// connect(pClientConnection, &QTcpSocket::disconnected, this, &SimpleTcpSocketServerDemo::deleteLater);
// pClientConnection->disconnectFromHost();
}
void SimpleTcpSocketServerDemo::displayError(QAbstractSocket::SocketError socketError)
{ 
 
qDebug() << "SimpleTcpSocketServerDemo::displayError " << socketError;
}
void testSimpleTcpSocketServerDemo()
{ 
 
//這樣寫會(huì)內(nèi)存泄漏,如此寫方便測(cè)試。
SimpleTcpSocketServerDemo* pSimpleTcpSocketServer = new SimpleTcpSocketServerDemo;
}

客戶端

頭文件

#pragma once
//
//客戶端
#include <QObject>
#include <QAbstractSocket>
#include <QRunnable>
#include <QThreadPool>
class QTcpSocket;
class SimpleTcpSocketClientDemo : public QObject
{ 
 
Q_OBJECT
public:
SimpleTcpSocketClientDemo();
private slots:
void connected();
void readyRead();
void error(QAbstractSocket::SocketError socketError);
private:
QTcpSocket* m_pTcpSocket;
};
class ClientRunnable : public QRunnable
{ 
 
public:
void run();
};
void testSimpleTcpSocketClientDemo();

源文件

#include "SimpleTcpSocketClientDemo.h"
#include <QTcpSocket>
#include <QDebug>
SimpleTcpSocketClientDemo::SimpleTcpSocketClientDemo()
{ 
 
//1. 創(chuàng)建TCP套接字對(duì)象
m_pTcpSocket = new QTcpSocket(this);
//2. 已連接、數(shù)據(jù)可讀、失敗信號(hào)連接
connect(m_pTcpSocket, &QTcpSocket::connected, this, &SimpleTcpSocketClientDemo::connected);
connect(m_pTcpSocket, &QIODevice::readyRead, this, &SimpleTcpSocketClientDemo::readyRead);
typedef void (QAbstractSocket::*QAbstractSocketErrorSignal)(QAbstractSocket::SocketError);
connect(m_pTcpSocket, static_cast<QAbstractSocketErrorSignal>(&QTcpSocket::error), this, &SimpleTcpSocketClientDemo::error);
//3. 與服務(wù)器端建立連接
m_pTcpSocket->connectToHost("127.0.0.1", 8888);
//4. 同步處理-等待數(shù)據(jù)可讀
m_pTcpSocket->waitForReadyRead();
}
void SimpleTcpSocketClientDemo::readyRead()
{ 
 
qDebug() << "SimpleTcpSocketClientDemo::readyRead " << m_pTcpSocket->readAll();
}
void SimpleTcpSocketClientDemo::connected()
{ 
 
qDebug() << "SimpleTcpSocketClientDemo::connected successfully";
}
void SimpleTcpSocketClientDemo::error(QAbstractSocket::SocketError socketError)
{ 
 
qDebug() << "SimpleTcpSocketClientDemo::error " << socketError;
}
void ClientRunnable::run()
{ 
 
//這樣寫會(huì)內(nèi)存泄漏,如此寫方便測(cè)試。
SimpleTcpSocketClientDemo* pSimpleTcpSocketClient = new SimpleTcpSocketClientDemo;
}
#define CLINET_COUNT 2000 //客戶端的數(shù)量
void testSimpleTcpSocketClientDemo()
{ 
 
QTime oTime;
oTime.start();
//同步線程池的方式模擬多個(gè)客戶端與服務(wù)器端交互
for (int nIndex = 0; nIndex < CLINET_COUNT; ++nIndex)
{ 
 
ClientRunnable* pRunnable = new ClientRunnable;
pRunnable->setAutoDelete(false);
QThreadPool::globalInstance()->start(pRunnable);
}
QThreadPool::globalInstance()->waitForDone(30 * 1000);
qDebug() << "connect count: " << CLINET_COUNT << "total time: " << (double)oTime.elapsed() / double(1000) << "s";
}

測(cè)試結(jié)果-單線程

服務(wù)器端

SimpleTcpSocketServerDemo::readDataFromClient  QTcpSocket(0x2f27f308)
SimpleTcpSocketServerDemo::writeDataToClient  "You will feel hungry again in another hour."
SimpleTcpSocketServerDemo::readDataFromClient  QTcpSocket(0x2eb61cf0)
SimpleTcpSocketServerDemo::writeDataToClient  "You might have mail."
.........

客戶端

SimpleTcpSocketClientDemo::connected  successfully
SimpleTcpSocketClientDemo::readyRead  "You might have mail."
SimpleTcpSocketClientDemo::connected  successfully
SimpleTcpSocketClientDemo::readyRead  "You will feel hungry again in another hour."
.........
connect count:  2000 total time:  3.926 s

通過(guò)測(cè)試輸出,可以看到服務(wù)器端與客戶端建立了正確的連接并且數(shù)據(jù)交換。

– 實(shí)際測(cè)試數(shù)據(jù):2000個(gè)連接,耗時(shí)4s左右,CPU使用率10%左右。

通過(guò)閱讀服務(wù)器端,發(fā)現(xiàn)單線程處理客戶端的連接效率較低。服務(wù)器端可修改為多線程處理客戶端連接,代碼如下:

服務(wù)器端-多線程

頭文件

#pragma once
//
//服務(wù)器端-多線程處理客戶端連接
#include <QTcpServer>
#include <QThread>
class MultiThreadTcpSocketServerDemo : public QTcpServer
{ 
 
public:
MultiThreadTcpSocketServerDemo();
//This virtual function is called by QTcpServer when a new connection is available. 
//The socketDescriptor argument is the native socket descriptor for the accepted connection.
virtual void incomingConnection(qintptr handle);
private:
QStringList m_oData;
};
//處理線程
class ServerHandleThread : public QThread
{ 
 
Q_OBJECT
public:
ServerHandleThread(qintptr handle, const QString& sWriteData);
virtual void run();
private:
qintptr m_nHandle;
QString m_sWriteData;
};
void testMultiThreadTcpSocketServerDemo();

//This virtual function is called by QTcpServer when a new connection is available. //The socketDescriptor argument is the native socket descriptor for the accepted connection. virtual void incomingConnection(qintptr handle); //該虛函數(shù)是重點(diǎn)

源文件

#include "MultiThreadTcpSocketServerDemo.h"
#include <QDebug>
#include <QTcpSocket>
MultiThreadTcpSocketServerDemo::MultiThreadTcpSocketServerDemo()
{ 
 
//初始換原始數(shù)據(jù)
m_oData << tr("You've been leading a dog's life. Stay off the furniture.")
<< tr("You've got to think about tomorrow.")
<< tr("You will be surprised by a loud noise.")
<< tr("You will feel hungry again in another hour.")
<< tr("You might have mail.")
<< tr("You cannot kill time without injuring eternity.")
<< tr("Computers are not intelligent. They only think they are.");
}
void MultiThreadTcpSocketServerDemo::incomingConnection(qintptr handle)
{ 
 
//獲取服務(wù)端數(shù)據(jù)
QString sWriteData = m_oData.at(qrand() % m_oData.size());
qDebug() << "MultiThreadTcpSocketServerDemo::incomingConnection" << handle;
ServerHandleThread* pThread = new ServerHandleThread(handle, sWriteData);
connect(pThread, &ServerHandleThread::finished, pThread, &ServerHandleThread::deleteLater);
pThread->start();
}
ServerHandleThread::ServerHandleThread(qintptr handle, const QString& sWriteData)
:m_sWriteData(sWriteData), m_nHandle(handle)
{ 
 
}
void ServerHandleThread::run()
{ 
 
//1. 建立與客戶端通信的TCP套接字
QTcpSocket oTcpSocket;
if (!oTcpSocket.setSocketDescriptor(m_nHandle))
{ 
 
qDebug() << "oTcpSocket.setSocketDescriptor error";
return;
}
//2. 向客戶端寫數(shù)據(jù)
qDebug() << "MultiThreadTcpSocketServerDemo::readDataFromClient" << &oTcpSocket;
qDebug() << "MultiThreadTcpSocketServerDemo::writeDataToClient" << m_sWriteData;
oTcpSocket.write(m_sWriteData.toUtf8());
oTcpSocket.disconnectFromHost();
oTcpSocket.waitForDisconnected();
}
void testMultiThreadTcpSocketServerDemo()
{ 
 
//1. 建立服務(wù)器端套接字
MultiThreadTcpSocketServerDemo* m_pTcpServer = new MultiThreadTcpSocketServerDemo();
//2. 啟動(dòng)服務(wù)端
if (!m_pTcpServer->listen(QHostAddress::Any, 8888))
{ 
 
qDebug() << "m_pTcpServer->listen() error";
}
}

測(cè)試結(jié)果-多線程

客戶端

SimpleTcpSocketClientDemo::connected  successfully
SimpleTcpSocketClientDemo::readyRead  "You might have mail."
SimpleTcpSocketClientDemo::connected  successfully
SimpleTcpSocketClientDemo::readyRead  "You will feel hungry again in another hour."
.........
connect count:  2000 total time:  6.403 s

– 實(shí)際測(cè)試數(shù)據(jù):2000個(gè)連接,耗時(shí)6.5s左右,CPU使用率20%左右。

可見(jiàn)服務(wù)器端采用多線程可充分利用CPU,但是頻繁的切換線程也會(huì)性能下降(耗時(shí))。

通過(guò)本案例的代碼實(shí)現(xiàn)可以了解TCP服務(wù)器端/客戶端編程的基本思路。并且驗(yàn)證了服務(wù)器端單線程和多線程的效率對(duì)比。 在windows中,可通過(guò)IOCP提高服務(wù)期端的效率,后面會(huì)詳細(xì)講解。

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

相關(guān)文章

  • C++?STL?iota?和?atoi?用法示例詳解

    C++?STL?iota?和?atoi?用法示例詳解

    atoi是一個(gè)C/C++標(biāo)準(zhǔn)庫(kù)中的函數(shù),用于將一個(gè)以ASCII字符串表示的整數(shù)轉(zhuǎn)換為整數(shù)類型,這篇文章主要介紹了C++?STL?iota?和?atoi?用法,需要的朋友可以參考下
    2024-08-08
  • C++中菱形繼承的解釋與處理詳解

    C++中菱形繼承的解釋與處理詳解

    菱形繼承是多重繼承中跑不掉的,Java拿掉了多重繼承,輔之以接口。C++中雖然沒(méi)有明確說(shuō)明接口這種東西,但是只有純虛函數(shù)的類可以看作Java中的接口,下面這篇文章主要給大家介紹了關(guān)于C++中菱形繼承的解釋與處理的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • C++11中bind綁定器和function函數(shù)對(duì)象介紹

    C++11中bind綁定器和function函數(shù)對(duì)象介紹

    這篇文章主要介紹了C++11中bind綁定器和function函數(shù)對(duì)象介紹,綁定器,函數(shù)對(duì)象和lambda表達(dá)式只能使用在一條語(yǔ)句中,更多相關(guān)內(nèi)容需要的小伙伴可以參考一下
    2022-07-07
  • C++中std::deque的使用

    C++中std::deque的使用

    std::deque是C++標(biāo)準(zhǔn)庫(kù)中的一個(gè)雙端隊(duì)列容器,本文主要介紹了C++中std::deque的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • C語(yǔ)言實(shí)現(xiàn)的猴子分桃問(wèn)題算法解決方案

    C語(yǔ)言實(shí)現(xiàn)的猴子分桃問(wèn)題算法解決方案

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)的猴子分桃問(wèn)題算法,較為詳細(xì)的分析了猴子分桃問(wèn)題算法的原理與通過(guò)遞歸算法解決問(wèn)題的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-10-10
  • c++調(diào)用python實(shí)現(xiàn)圖片ocr識(shí)別

    c++調(diào)用python實(shí)現(xiàn)圖片ocr識(shí)別

    所謂c++調(diào)用python,實(shí)際上就是在c++中把整個(gè)python當(dāng)作一個(gè)第三方庫(kù)引入,然后使用特定的接口來(lái)調(diào)用python的函數(shù)或者直接執(zhí)行python腳本,本文介紹的是調(diào)用python實(shí)現(xiàn)圖片ocr識(shí)別,感興趣的可以了解下
    2023-09-09
  • Qt 智能指針的具體使用

    Qt 智能指針的具體使用

    本文主要介紹了Qt 智能指針的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • C++函數(shù)模板與類模板實(shí)例解析

    C++函數(shù)模板與類模板實(shí)例解析

    這篇文章主要介紹了C++函數(shù)模板與類模板,需要的朋友可以參考下
    2014-08-08
  • C++ STL入門教程(1) vector向量容器使用方法

    C++ STL入門教程(1) vector向量容器使用方法

    這篇文章主要為大家詳細(xì)介紹了C++ STL入門教程第一篇,vector向量容器使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • C語(yǔ)言實(shí)現(xiàn)繪制余弦曲線

    C語(yǔ)言實(shí)現(xiàn)繪制余弦曲線

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)繪制余弦曲線的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01

最新評(píng)論

岑溪市| 桂东县| 浑源县| 天门市| 巫溪县| 铁岭市| 湖口县| 金阳县| 濉溪县| 德州市| 疏勒县| 井冈山市| 沙湾县| 桂林市| 罗城| 上饶县| 东乡县| 宝山区| 临江市| 高邑县| 班玛县| 武川县| 墨竹工卡县| 潜山县| 运城市| 略阳县| 栾川县| 霍山县| 侯马市| 名山县| 扎鲁特旗| 北碚区| 宁夏| 丽水市| 名山县| 南皮县| 无棣县| 乌拉特前旗| 凉山| 株洲县| 广平县|