1. 程式人生 > >Qt實用技巧:Qt併發伺服器通訊,受同一時刻最大執行緒數限制(筆者本本同一時刻600多)

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使用2QT例程

目錄 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