Qt實用技巧:Qt併發伺服器通訊,受同一時刻最大執行緒數限制(筆者本本同一時刻600多)
需求
預言專案需要寫個qt伺服器,終端與qt伺服器完成socket通訊,因存在多個裝置,單個傳輸檔案大小比較大,所以做多執行緒併發。
實現原理
客戶端:固定client的執行緒數量,單個執行緒按照設定的間隔不斷髮送資料給伺服器,並接收伺服器的執行緒指標地址。
服務端:主執行緒為TcpServer,當有一個新連線的時候,會new一個執行緒處理該新連線socket,接收資料後傳送處理該socket的執行緒地址。
Demo
受限說明
1.同一時刻該應用最大限度的執行緒數,如果超過則仍然會new,然後列印失敗,但是仍然會跑new執行緒的建構函式;
2.下載原始碼可以將客戶端的時間間隔改下,同時執行執行緒數增大,IDE的qDebug可以看到停止後,index沒有歸零,仔細翻閱除錯資訊,可以找到“錯誤”,此條,以便讀者自己可以使用原始碼嘗試該問題。
3.寫伺服器時,應對最大執行緒數做限制,此Demo只是專案過程中關鍵功能的記錄,未做處理。
實現截圖
關鍵程式碼
客戶端
單個執行緒socket請求程式碼 TcpClientThread.h
#ifndefTCPCLIENTTHREAD_H
#defineTCPCLIENTTHREAD_H
#include<QThread>
#include<QTcpSocket>
#include<QByteArray>
#include<QHostAddress>
/************************************************************\
*類名:TcpClientThread
*描述:執行緒迴圈使用QTcpClient連線伺服器傳送資料、接收資料、斷開
*訊號:
*recvMsg()-收到客戶端的的資料
*函式:
*TcpClientThread()-傳入ip,port,間隔時間(ms)
*start()-開啟執行緒
*stop()-停止
*作者:紅模仿QQ:21497936
*日期版本號描述
*2018年04月13日v1.0.0指定間隔向指定ip和port傳送資料、接收資料
\************************************************************/
classTcpClientThread:publicQThread
{
Q_OBJECT
public:
explicitTcpClientThread(QStringip,quint16port,intms=1000,QObject*parent=nullptr);
signals:
voidrecvData(QByteArraydata);
publicslots:
voidstop();
protected:
voidrun();
private:
QTcpSocket*_pTcpSocket;
QString_ip;
quint16_port;
bool_running;
int_ms;
};
#endif//TCPCLIENTTHREAD_H
TcpClientThread.cpp
#include "tcpclientthread.h"
#include <QDebug>
TcpClientThread::TcpClientThread(QString ip, quint16 port, int ms, QObject *parent)
: QThread(parent)
{
_ip = ip;
_port = port;
_ms = ms;
}
void TcpClientThread::stop()
{
_running = false;
}
void TcpClientThread::run()
{
_running = true;
// 多執行緒new的物件不要直接指定父類,到時可以類似於下面指定父類
// 直接指定錯誤,提示
// QObject: Cannot create children for a parent that is in a different thread.
// (Parent is TcpClientThread(0x1b4b2f28), parent's thread is QThread(0xcb6bcd0),
// current thread is TcpClientThread(0x1b4b2f28)
_pTcpSocket = new QTcpSocket();
// 示例說明:可以指定本執行緒中new的類作為父類,因為_pTcpSocket是在本類中new的
// _pTcpSocket = new QTcpSocket(_pTcpSocket);
while(true)
{
if(!_running)
{
qDebug() <<__FILE__<<__LINE__ << "exit from thread";
break;
}
_pTcpSocket->connectToHost(QHostAddress(_ip), _port);
if(!_pTcpSocket->waitForConnected())
{
qDebug() <<__FILE__<<__LINE__ << "Failed to connect to host"
<< QHostAddress(_ip).toString() << ":" << _port
<< _pTcpSocket->errorString();
continue;
}
QString data = "test infomation";
_pTcpSocket->write(data.toUtf8());
_pTcpSocket->waitForBytesWritten(3000);
_pTcpSocket->waitForReadyRead(3000);
QByteArray byteArray = _pTcpSocket->readAll();
_pTcpSocket->disconnectFromHost();
emit recvData(byteArray);
QThread::msleep(_ms);
}
delete _pTcpSocket;
}
伺服器端
newConnection執行緒處理程式碼Thread.h
#ifndefTHREAD_H
#defineTHREAD_H
#include<QObject>
#include<QThread>
#include<QTcpSocket>
#include<QDebug>
#include<QMutexLocker>
/************************************************************\
*類名:Thread
*描述:伺服器端,執行緒處理新連線的socket
*訊號:
*Thread()-傳入socket描述符,注意型別是qintptr,不是int
*error()-錯誤資訊
*recvMsg()-收到客戶端的的資料
*函式:
*TcpClientThread()-傳入ip,port,間隔時間(ms)
*start()-開啟執行緒
*stop()-停止
*作者:紅模仿QQ:21497936
*日期版本號描述
*2018年04月13日v1.0.0處理收到的資訊
\************************************************************/
#defineDEBUGqDebug()<<__FILE__<<__LINE__<<__FUNCTION__<<"currentthread:"<<QThread::currentThread()
classThread:publicQThread
{
Q_OBJECT
public:
explicitThread(qintptrsocketDescriptor,QThread*parent=nullptr);
~Thread();
signals:
voiderror(QStringerrorString);
voidrecvMsg(QStringmsg);
protectedslots:
voidreadyRead();
protected:
voidrun();
private:
qintptr_socketDescriptor;
QTcpSocket*_pTcpSoscket;
staticint_count;
staticQMutex_mutex;
int_index;
};
#endif//THREAD_Hsa
Thread.cpp
#include "thread.h"
#include <QHostAddress>
int Thread::_count = 0;
QMutex Thread::_mutex;
Thread::Thread(qintptr socketDescriptor, QThread *parent)
: QThread(parent)
{
_socketDescriptor = socketDescriptor;
DEBUG;
_mutex.lock();
_index = _count;
_count++;
DEBUG << _count;
_mutex.unlock();
}
Thread::~Thread()
{
DEBUG;
_mutex.lock();
_count--;
DEBUG << _count;
_mutex.unlock();
}
void Thread::readyRead()
{
DEBUG;
QString msg;
QByteArray recvData = _pTcpSoscket->readAll();
_mutex.lock();
QByteArray sendData = QString("伺服器處理該socket的執行緒地址為:%1, index:%2").arg((quint64)QThread::currentThread()).arg(_index).toUtf8() ;
_mutex.unlock();
_pTcpSoscket->write(sendData);
_pTcpSoscket->waitForBytesWritten(1000);
_pTcpSoscket->close();
msg += QString(recvData) + ", sendTo" + _pTcpSoscket->peerAddress().toString() + QString(":%1").arg(_pTcpSoscket->peerPort()) + QString(sendData);
emit recvMsg(msg);
}
void Thread::run()
{
DEBUG;
_pTcpSoscket = new QTcpSocket;
if(!_pTcpSoscket->setSocketDescriptor(_socketDescriptor))
{
emit error(_pTcpSoscket->errorString());
return;
}
// Qt::DirectConnection 執行緒內傳遞訊息,若使用預設的,則會在主執行緒當中處理
connect(_pTcpSoscket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
connect(_pTcpSoscket, SIGNAL(disconnected()), this, SLOT(quit()));
exec();
}
相關推薦
Qt實用技巧:Qt併發伺服器通訊,受同一時刻最大執行緒數限制(筆者本本同一時刻600多)
需求 預言專案需要寫個qt伺服器,終端與qt伺服器完成socket通訊,因存在多個裝置,單個傳輸檔案大小比較大,所以做多執行緒併發。實現原理 客戶端:固定client的執行緒數量,單個執行緒按照設定的間隔不斷髮送資料給伺服器,並接收伺服器的執行緒指
.NET執行緒池最大執行緒數的限制-記一次IIS併發瓶頸
.NET ThreadPool 最大執行緒數的限制 IIS併發瓶頸,有幾個地方,IIS執行緒池的最大佇列數,工作程序數,最大併發數。這些這裡就不展開。主要是最近因為過度使用Task 導致的執行緒數佔用過多,所以實驗了一下 .net執行緒池 的限制,分享一下。 注意IIS執行緒池與.NET執行緒池不是同一個東西
Qt實用技巧:使用QMediaPlayer播放mp4檔案
需求 做軟體時,點選一個按鈕切入另一個介面,需要播放一段動畫 原理 使用QMediaplayer,QVideoWidget,QMediaPlaylist實現,注意安裝解碼器 lavfilter(本機可播放,但qt不能播放,可能是解碼器的原因)
Qt實用技巧:使用Qt給指定手機發送簡訊(點對點、群發等等)
需求 軟體控制簡訊提醒客戶驗證碼等等,如生日提醒、購買提醒、時間限制等等。Demo下載地址Demo效果截圖簡訊平臺介紹 軟體傳送簡訊需要第三方平臺支援,步驟如下: 1.註冊指定雲平臺賬戶,一般有免費簡訊條數,筆者使用“雲通知”;
Qt實用技巧:ubuntu釋出程式打包流程(解決外掛xcb載入失敗)
原博主部落格地址:https://blog.csdn.net/qq21497936 本文章部落格地址:https://blog.csdn.net/qq21497936/article/details/85396652
Qt實用技巧:使用Qt載入超大圖片的耗時測試
需求 某機器人專案中,需要載入構建的地圖,此處僅測試直接載入圖片的時間。 相關部落格 《QT三大繪圖類:QPixmap/QImage/QPicture》:https://blog.csdn.net/qq2149
Qt實用技巧:設計模式之單例模式,唯一例項類通用模板
需求 Qt常需要一個類,全域性呼叫,是設計模式中的單例模式。 單例模式 單例模式,是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。通過單例模式可以保證系統中,應用該模式的類一個類只有一個例項。即一個類只有一個物
Qt實用技巧:會呼吸的痛(呼吸點/呼吸燈)
Qt實用技巧:會呼吸的痛(呼吸點/呼吸燈) 感謝 Demo效果 入坑 主視窗為QWidget的子類時,不論設定QPallet和setStyleSheets設定背景圖片是無法生效的,但設定顏色卻可以生效。 Demo目錄結構
Qt實用技巧:使用QMediaPlayer和Windows自帶元件播放swf、rmvb、mpg、mp4等視訊檔案
需求 做軟體時,點選進入介面需要播放一段視訊,該視訊的格式可相容swf、rmvb、mpg、mp4等視訊檔案。 原理 使用QMediaPlayer播放rmvb、mpg、mp4格式 使用windows Media Player
Qt實用技巧:基於tcp的C/S構架多人聊天程式(線上、離線、離線資訊再次登入後傳送等)
需求 多人聊天室程式,基於TCP和C/S構架,需要離線後可對離線者傳送資訊,待離線者上線後可收到上次傳送的離線資訊 技術點 1.TCP連線伺服器 2.伺服器得儲存所有客戶端列表,包括線上的不線上的 3.伺服器得通知每個客戶端當前線上
Qt實用技巧:QPainterPath繪圖路徑(多次畫同樣的圖形集合)
需求 根據配置檔案,可不改變程式只調整配置檔案可調整主頁面上的字串。 原理 1.讀取檔案,固定格式(檔案在本文章中省略) 2.寫一串字元,使用QPainterPath 3.注意QPainter的時候,需
併發伺服器三種實現方式之程序、執行緒和select
前言:剛開始學網路程式設計,都會先寫一個客戶端和服務端,不知道你們有沒有試一下:再開啟一下客戶端,是連不上服務端的。還有一個問題不知道你們發現沒:有時啟伺服器,會提示“Address already in use”,過一會就好了,想過為啥麼?在這篇部落格會解釋這個問題。 但現實的伺服器都會連很多客戶
作業題:輸入4個整數,找出其中最大的數。用一個函數來實現. 分別使用結構化方法和函數嵌套的方法。
system 是否 進行 如果 div 使用 clu 函數 整型 之前在main()函數中的思路是: #include <iostream> using namespace std; int main(){ //求四個數中最大的數? /
Qt開發技巧:編寫.pro檔案,在構建流程中加入命令列的方法
1、在專案構建前執行命令 在專案構建前執行命令cmd 存在問題 system(cmd) 存在執行多次的問題,可以參考message函式的QMake Manual說明
QT使用2:QT例程
目錄 test 官方文檔 快捷 流程 href 網站 擴展 time 轉至:http://blog.51cto.com/9291927/2138876 Qt開發學習教程 一、Qt開發基礎學習教程 本部分博客主要根據狄泰學院唐老師的《QT實驗分析教程》創作,同時根據天山老妖自
實用技巧:Spring Cloud中,如何優雅下線微服務?
原文:http://www.itmuch.com/spring-cloud-sum/how-to-unregister-service-in-eureka/ ,轉載請說明出處。 在生產環境中,服務的上下線是不可避免的,我們希望能夠優雅地下線微服務。本文基於Spring Boot 2.x + Spring
QT | 已解決:pure virtual method called ,terminate called without an active exception
在模擬一個編輯器時,在實現高亮時,針對每種程式語言,都新建一個類繼承了QSyntaxHighlighter高亮類。 接著在mainWindow中設定每個程式語言的選單項,都設定為可選擇型。 mainWindow中宣告一個QSyntaxHighlighter類的指標highlighter,
【本人禿頂程式設計師】實用技巧:Spring Cloud中,如何優雅下線微服務
←←←←←←←←←←←← 我都禿頂了,還不點關注! 在生產環境中,服務的上下線是不可避免的,我們希望能夠優雅地下線微服務。本文基於Spring Boot 2.x + Spring Cloud Finchley講解實際專案中優雅下線服務的四種方式,並探討各方式的優缺點。 注:S
實用技巧:教你如何在沒有網路的Linux機器上快速安裝軟體
相信很多人遇到過這樣的問題: 你需要在公司的一臺伺服器上安裝xxx軟體,例如vsftpd; 該伺服器無法連線公網; 這臺伺服器很可能是一個最簡安裝的Linux(意味著該機器可能有很多常見的軟體依賴缺失),你也搞不清楚究竟是不是最簡安裝的,只能用uname -a&
Qt學習筆記:Qt 事件機制
一、Qt中的事件處理 1. 在Qt中,事件被封裝成一個個物件,所有的事件均繼承自抽象類QEvent. 事件處理的核心包括事件①產生、②分發、③接受和處理。 事件的產生: 誰來產生事件? 最容易想到的是我們的輸入裝置,比如鍵盤、滑鼠產生的keyPressEvent,keyR