国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++ Qt TCP的心跳檢測(cè)機(jī)制,斷線重連技術(shù),應(yīng)用層代碼重新實(shí)現(xiàn)

這篇具有很好參考價(jià)值的文章主要介紹了C++ Qt TCP的心跳檢測(cè)機(jī)制,斷線重連技術(shù),應(yīng)用層代碼重新實(shí)現(xiàn)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

前言:

一、Qt直接啟動(dòng)本身的KeepAlive

二、在應(yīng)用層自己實(shí)現(xiàn)一個(gè)心跳檢測(cè)

?三、自定義心跳代碼實(shí)現(xiàn):

完整客戶端服務(wù)端工程下載:

共用的結(jié)構(gòu)體相關(guān)頭文件:

? ? ? ? 客戶端部分核心代碼:

? ? ? ? 服務(wù)端部分核心代碼:

運(yùn)行結(jié)果展示:


前兩篇關(guān)于qt tcp 相關(guān)的,可以通過(guò)以下傳送門查看:

Qt TCP相關(guān)的一些整理:客戶端常見(jiàn)操作 socket 通信 network-CSDN博客

Qt TCP相關(guān)的一些整理:服務(wù)端常見(jiàn)操作 socket 通信 network-CSDN博客

前言:

? ? ? ? TCP本身是有一個(gè)?;顮顟B(tài)的 keep-alive機(jī)制,默認(rèn)是關(guān)閉的,需要單獨(dú)啟動(dòng)就可以;默認(rèn)保活時(shí)間是2小時(shí),不過(guò)這個(gè)機(jī)制是在協(xié)議層,也就是傳輸層生效的,如果應(yīng)用層出問(wèn)題了,就不能及時(shí)發(fā)現(xiàn)問(wèn)題;如果想要實(shí)現(xiàn)斷線重連的操作,這個(gè)就不好實(shí)現(xiàn)了。

? ? ? ? 另一種方式,可以在應(yīng)用層自定義模擬這個(gè)心跳檢測(cè)機(jī)制,使用線程或者定時(shí)器來(lái)定時(shí)發(fā)心跳包即可實(shí)現(xiàn)?;罟δ?,并且能做到斷線重連的操作。

一、Qt直接啟動(dòng)本身的KeepAlive

    m_client = new QTcpSocket(this);
    // 啟動(dòng)心跳檢測(cè)
    m_client->setSocketOption(QAbstractSocket::KeepAliveOption,true);
    m_client->connectToHost("127.0.0.1",8898);

二、在應(yīng)用層自己實(shí)現(xiàn)一個(gè)心跳檢測(cè)

? ? ? ? 客戶端部分:需要使用定時(shí)器來(lái)定時(shí)發(fā)送心跳包,并且根據(jù)間隔和?;羁倳r(shí)長(zhǎng)來(lái)設(shè)定一個(gè)閾值次數(shù),一開(kāi)始按最大時(shí)長(zhǎng)的次數(shù)來(lái)初始化,當(dāng)不停的遞減閾值為0時(shí),就需要斷線,如果需要重連,那就重新連接一下;當(dāng)然收到包時(shí),需要重置閾值;

? ? ? ? 服務(wù)端部分:需要使用一個(gè)map容器來(lái)保存已經(jīng)連上的套接字及閾值,起一條線程來(lái)定時(shí)輪詢?nèi)萜鳎?dāng)發(fā)現(xiàn)閾值為0時(shí)則斷線,并且從容器中刪除鍵值對(duì);當(dāng)新的客戶端連接成功連上時(shí),要增加新的鍵值對(duì)到map容器中;當(dāng)收到數(shù)據(jù)包時(shí),要對(duì)閾值進(jìn)行重置;

?三、自定義心跳代碼實(shí)現(xiàn):

完整客戶端服務(wù)端工程下載:

點(diǎn)我下載

共用的結(jié)構(gòu)體相關(guān)頭文件:

struct_data.h 源碼
#ifndef STRUCT_DATA_H
#define STRUCT_DATA_H

enum TypeInfo{
    HEART_CHECK_REQ,   // 心跳檢測(cè)請(qǐng)求
    HEART_CHECK_RES,   // 心跳檢測(cè)響應(yīng)
};

struct Head
{
    int type;
    int len;
};

struct HeartCheckReq
{
    Head head;
    HeartCheckReq() {
        head.type = HEART_CHECK_REQ;
        head.len = sizeof(HeartCheckReq);
    }
};

struct HeartCheckRes
{
    Head head;
    HeartCheckRes() {
        head.type = HEART_CHECK_RES;
        head.len = sizeof(HeartCheckRes);
    }
};

#endif // STRUCT_DATA_H

? ? ? ? 客戶端部分核心代碼:

頭文件代碼:?

#ifndef TCPMAINWINDOW_H
#define TCPMAINWINDOW_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QTimer>
#include <QTime>
#include "struct_data.h"

namespace Ui {
class TcpMainWindow;
}

class TcpMainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit TcpMainWindow(QWidget *parent = 0);
    ~TcpMainWindow();

private slots:
    void myRead();  // 收包槽函數(shù)

    void on_pushButton_clicked();

    void heartCheckSlot(); // 定時(shí)發(fā)心跳包的槽

private:
    Ui::TcpMainWindow *ui;
    QTcpSocket *m_client;
    int m_heartCheckTimes;
    QTimer *m_checkTimer;

};

#endif // TCPMAINWINDOW_H

源文件代碼:

#include "tcpmainwindow.h"
#include "ui_tcpmainwindow.h"
#include <QDebug>

#define HEART_CHECK_TIMES 6 // ?;?0秒,每5秒發(fā)一次心跳包,閾值為6

TcpMainWindow::TcpMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::TcpMainWindow)
{
    ui->setupUi(this);
    m_client = new QTcpSocket(this);
    // 啟動(dòng)tcp默認(rèn)的保活
    //m_client->setSocketOption(QAbstractSocket::KeepAliveOption,true);
    m_client->connectToHost("127.0.0.1",8898);
    if(m_client->waitForConnected()){
        qDebug()<<"conn ok";
        connect(m_client,SIGNAL(readyRead()),this,SLOT(myRead()));
        m_heartCheckTimes = HEART_CHECK_TIMES; // 閾值初始化
        // 心跳檢測(cè)相關(guān)的定時(shí)器 和 關(guān)聯(lián)操作
        m_checkTimer = new QTimer(this);
        connect(m_checkTimer,SIGNAL(timeout()),this,SLOT(heartCheckSlot()));
        m_checkTimer->start(5000); // 5秒的間隔定時(shí)

    }else{
        qDebug()<<"conn fail"<<m_client->errorString();
    }
}

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

void TcpMainWindow::myRead()
{
    QByteArray buffer = m_client->readAll();
    qDebug()<<buffer;
    // 只是簡(jiǎn)單的打印輸出,還沒(méi)有做解包處理

    m_heartCheckTimes = HEART_CHECK_TIMES;
}

void TcpMainWindow::on_pushButton_clicked()
{
    char buffer[] = "碼蟻軟件歡迎您";
    qDebug()<<m_client->write(buffer,sizeof(buffer));
}

void TcpMainWindow::heartCheckSlot()
{
    HeartCheckReq req;
    m_client->write((char*)&req,req.head.len); // 發(fā)送心跳包
    m_heartCheckTimes--; // 遞減閾值
    ui->textBrowser->append(QString("當(dāng)前時(shí)間:%1 心跳閾值為 %2").arg(QTime::currentTime().toString()).arg(m_heartCheckTimes));
    if(m_heartCheckTimes <= 0){
        // 需要做斷線重連操作
        m_client->close();
        m_client->connectToHost("127.0.0.1",8898);
        if(m_client->waitForConnected()){
            m_heartCheckTimes = HEART_CHECK_TIMES; // 重連成功,重置閾值
            ui->textBrowser->append("重連成功");
        }
    }
}

? ? ? ? 服務(wù)端部分核心代碼:

頭文件代碼:?

#ifndef SERVERMAINWINDOW_H
#define SERVERMAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
#include "struct_data.h"

namespace Ui {
class ServerMainWindow;
}

class ServerMainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit ServerMainWindow(QWidget *parent = 0);
    ~ServerMainWindow();
private slots:
    void connectSlot(); // 處理連接的槽
    void clientSlot(); // 與客戶端交互的槽
    void checkTimer(); // 定時(shí)檢測(cè)心跳的槽
private:
    Ui::ServerMainWindow *ui;
    QTcpServer *m_server;
    QMap<QTcpSocket*,int> m_clients;
    QTimer *m_checkTimer;
};

#endif // SERVERMAINWINDOW_H

源文件代碼:

#include "servermainwindow.h"
#include "ui_servermainwindow.h"
#include <QDebug>

#define HEART_CHECK_TIMES 6

ServerMainWindow::ServerMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::ServerMainWindow)
{
    ui->setupUi(this);
    m_server = new QTcpServer(this);

    if(m_server->listen(QHostAddress::Any,8898)){
        qDebug()<<"listen ok";
        connect(m_server,SIGNAL(newConnection()),this,SLOT(connectSlot()));
        // 心跳檢測(cè)相關(guān)的定時(shí)器及關(guān)聯(lián)操作
        m_checkTimer = new QTimer(this);
        connect(m_checkTimer,SIGNAL(timeout()),this,SLOT(checkTimer()));
        m_checkTimer->start(5000);

    }else{
        qDebug()<<"listen fail"<<m_server->errorString();
    }

}

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

void ServerMainWindow::connectSlot()
{
    QTcpSocket *client = m_server->nextPendingConnection();
    client->setSocketOption(QAbstractSocket::KeepAliveOption,true);
    qDebug()<<client;
    if(!client->isValid()) return;
    m_clients[client] = HEART_CHECK_TIMES; // 用于心跳檢測(cè)的map
    // 關(guān)聯(lián)與客戶端通信的自定義收包槽
    connect(client,SIGNAL(readyRead()),this,SLOT(clientSlot()));
    QByteArray buffer = "歡迎來(lái)到碼蟻軟件服務(wù)器。";
    qDebug()<<client->write(buffer);
}

void ServerMainWindow::clientSlot()
{
    QTcpSocket * client = static_cast<QTcpSocket *>(sender());
    QByteArray buffer = client->readAll();
    qDebug()<<buffer.data();
    m_clients[client] = HEART_CHECK_TIMES; // 重置心跳閾值
    int type = ((Head*)buffer.data())->type;
    if(type == HEART_CHECK_REQ){
        ui->textBrowser->append(QString("收到 %1 端口 %2 心跳包").arg(client->peerAddress().toString()).arg(client->peerPort()));
        // 回一個(gè)響應(yīng)包
        HeartCheckRes res;
        client->write((char*)&res,res.head.len);
    }
}

void ServerMainWindow::checkTimer()
{
    for(auto it=m_clients.begin();it!=m_clients.end();){
        it.value()--;
        ui->textBrowser->append(QString("%1 %2 的閾值 %3").arg(it.key()->peerAddress().toString()).arg(it.key()->peerPort()).arg(it.value()));
        if(it.value()==0){
            ui->textBrowser->append(QString("發(fā)現(xiàn)無(wú)用連接 %1").arg(it.key()->peerAddress().toString()));
            it.key()->close();
            m_clients.erase(it++);
        }else{
            it++;
        }
    }
}

運(yùn)行結(jié)果展示:

qt tcp 心跳,Qt,tcp/ip,網(wǎng)絡(luò),服務(wù)器,c++,qt,算法,開(kāi)發(fā)語(yǔ)言

當(dāng)關(guān)閉服務(wù)端之后,再重新開(kāi)啟服務(wù)端:

qt tcp 心跳,Qt,tcp/ip,網(wǎng)絡(luò),服務(wù)器,c++,qt,算法,開(kāi)發(fā)語(yǔ)言文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-751625.html

到了這里,關(guān)于C++ Qt TCP的心跳檢測(cè)機(jī)制,斷線重連技術(shù),應(yīng)用層代碼重新實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • websocket斷線重連&&心跳檢測(cè)

    websocket斷線重連&&心跳檢測(cè)

    封裝websocket 實(shí)現(xiàn)斷線重連跟心態(tài)檢測(cè),使用的typeScript去封裝 在nodejs 安裝ws庫(kù) 代碼如下(示例): ?服務(wù)端實(shí)現(xiàn)ws 創(chuàng)建一個(gè)server.js 文件 運(yùn)行ws服務(wù) ? node .server.js? 客戶端實(shí)現(xiàn)websocket 創(chuàng)建一個(gè)socket.ts 文件 vue 頁(yè)面使用 斷開(kāi)ws服務(wù) 斷線? 啟動(dòng)服務(wù)后 自動(dòng)重連

    2024年01月19日
    瀏覽(25)
  • uniapp使用WebSocket斷線,心跳重連機(jī)制

    提示:我們?cè)谑褂肳ebSocket,經(jīng)常會(huì)遇到有的時(shí)候給別人發(fā)消息,別人會(huì)接收不到,這個(gè)時(shí)候就有可能是WebSocket斷線了,所以這個(gè)時(shí)候心跳包就出現(xiàn)了 提示:可直接使用,記得把對(duì)應(yīng)地址替換一下

    2024年04月12日
    瀏覽(31)
  • websocket實(shí)時(shí)通訊和socket.io實(shí)時(shí)通信庫(kù)的使用;心跳機(jī)制與斷線重連

    https://zh.javascript.info/websocket WebSocket 是一種網(wǎng)絡(luò)通信協(xié)議,就類似于 HTTP 也是一種通信協(xié)議。 為什么需要 WebSocket? 因?yàn)?HTTP 協(xié)議有一個(gè)缺陷:通信只能由客戶端發(fā)起。 代碼解析: 創(chuàng)建WebSocket實(shí)例:通過(guò) new WebSocket() 創(chuàng)建一個(gè)WebSocket實(shí)例。在括號(hào)中傳入服務(wù)器的URL,該URL指定了

    2024年02月16日
    瀏覽(39)
  • WebSocket心跳檢測(cè)和重連機(jī)制

    心跳和重連的目的用一句話概括就是客戶端和服務(wù)端保證彼此還活著,避免丟包發(fā)生。 websocket 連接斷開(kāi)有以下兩證情況: 前端斷開(kāi) 在使用 websocket 過(guò)程中,可能會(huì)出現(xiàn)網(wǎng)絡(luò)斷開(kāi)的情況,比如信號(hào)不好,或者網(wǎng)絡(luò)臨時(shí)關(guān)閉,這時(shí)候websocket的連接已經(jīng)斷開(kāi),而不同瀏覽器有不同

    2024年01月21日
    瀏覽(33)
  • C++ TCP/IP 關(guān)于tcp斷線重連的問(wèn)題

    在工控上經(jīng)常用到tcp連接,比如串口服務(wù)器或某些支持modbustcp協(xié)議的儀表等,以前盡量使用串口服務(wù)器的虛擬串口功能,現(xiàn)在逐步使用上了tcpserver或tcpclient模式。 搜索了個(gè)C++ 的tcp斷線重連的案例(http://www.cnblogs.com/kingdom_0/articles/2571727.html),使用這個(gè)的原因還因其使用的是

    2024年02月10日
    瀏覽(13)
  • SpringBoot+Netty實(shí)現(xiàn)TCP客戶端實(shí)現(xiàn)接收數(shù)據(jù)按照16進(jìn)制解析并存儲(chǔ)到Mysql以及Netty斷線重連檢測(cè)與自動(dòng)重連

    SpringBoot+Netty實(shí)現(xiàn)TCP客戶端實(shí)現(xiàn)接收數(shù)據(jù)按照16進(jìn)制解析并存儲(chǔ)到Mysql以及Netty斷線重連檢測(cè)與自動(dòng)重連

    在SpringBoot項(xiàng)目中需要對(duì)接三方系統(tǒng),對(duì)接協(xié)議是TCP,需實(shí)現(xiàn)一個(gè)TCP客戶端接收 服務(wù)端發(fā)送的數(shù)據(jù)并按照16進(jìn)制進(jìn)行解析數(shù)據(jù),然后對(duì)數(shù)據(jù)進(jìn)行過(guò)濾,將指定類型的數(shù)據(jù) 通過(guò)mybatis存儲(chǔ)進(jìn)mysql數(shù)據(jù)庫(kù)中。并且當(dāng)tcp服務(wù)端斷連時(shí),tcp客戶端能定時(shí)檢測(cè)并發(fā)起重連。 全流程效果 ?

    2024年02月03日
    瀏覽(18)
  • uniapp websocket機(jī)制 心跳 重連

    在開(kāi)發(fā)程序過(guò)程中通信功能還是比較常用到的,本文主要介紹的是uniapp中websocket的使用 websocket建立連接后,斷開(kāi)、心跳機(jī)制重新鏈接的一個(gè)過(guò)程。 關(guān)于uni.connectSocket可仔細(xì)閱讀uniapp官網(wǎng)中的uni.connetSocket以及連接socket創(chuàng)建的實(shí)例 SocketTask ? 具體代碼如下:內(nèi)有代碼詳細(xì)注解,

    2024年02月12日
    瀏覽(27)
  • java實(shí)現(xiàn)WebSocket客戶端&&斷線重連機(jī)制

    1、引入maven依賴(注意版本) 2、代碼

    2024年02月16日
    瀏覽(25)
  • Flutter:WebSocket封裝-實(shí)現(xiàn)心跳、重連機(jī)制

    前言Permalink Flutter簡(jiǎn)介 Flutter 是 Google推出并開(kāi)源的移動(dòng)應(yīng)用開(kāi)發(fā)框架,主打跨平臺(tái)、高保真、高性能。開(kāi)發(fā)者可以通過(guò) Dart語(yǔ)言開(kāi)發(fā) App,一套代碼同時(shí)運(yùn)行在 iOS 和 Android平臺(tái)。 Flutter提供了豐富的組件、接口,開(kāi)發(fā)者可以很快地為 Flutter添加 native擴(kuò)展。同時(shí) Flutter還使用 Nat

    2024年02月10日
    瀏覽(35)
  • TCP通訊(三次握手、四次揮手;滑動(dòng)窗口;TCP狀態(tài)轉(zhuǎn)換;端口復(fù)用;TCP心跳檢測(cè)機(jī)制)

    TCP通訊(三次握手、四次揮手;滑動(dòng)窗口;TCP狀態(tài)轉(zhuǎn)換;端口復(fù)用;TCP心跳檢測(cè)機(jī)制)

    ?前言:建議看著圖片,根據(jù)文字描述走一遍TCP通訊過(guò)程,加深理解。 目錄 TCP通信時(shí)序: 1)建立連接(三次握手)的過(guò)程: 2)數(shù)據(jù)傳輸?shù)倪^(guò)程: 3)關(guān)閉連接(四次揮手)的過(guò)程: 滑動(dòng)窗口 (TCP流量控制): TCP狀態(tài)轉(zhuǎn)換: 半關(guān)閉: 2MSL: 程序設(shè)計(jì)中的問(wèn)題: 端口復(fù)用:

    2024年02月03日
    瀏覽(18)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包