qtcpsocket断开_Qt中,网络连接状态分析及心跳包的使用与实现(点赞)

总第22篇

在开发网络通信系统的过程中,有时客户端必须要知道网络的连接状态,而客户端与服务器断开连接的因素有很多。本文将综合分析各种情况,在此基础上介绍心跳包的使用与代码实现。

1.不同的网络断开连接情况

在常见的C/S结构系统中,网络断开连接状况主要可分为下面六种:客户端网线断开;

客户端网络断开;

客户端通过Http代理连接服务器,代理机器断开代理;

客户端通过Http代理连接服务器,代理机器网络断开;

客户端通过Http代理连接服务器,代理机器的网线断开;

服务器断开;

对于上面的六种情况,又可从连接服务器之前和连接服务器之后两方面来分析。

连接服务器之前:

对于第1种情况【客户端网线断开】,此时用socket调用connectToHost()方法连接服务器会立即触发 QTcpSocket的error信号, 我们可以绑定相应的信号槽去处理连接失败的结果。

对于第2-6种情况,此时用socket调用connectToHost()方法连接服务器并不会立即触发QTcpSocket的error信号, 而是经过40s以上的连接等待超时后才发出error信号。

连接上服务器之后:

对于第1种情况【客户端网线断开】,此时socket不会发送error信号,也不会发送disconnect信号, 这是因为网线是属于物理链路层的,tcp无法觉察到,socket仍处于连接状态。

对于第2-3种情况, 此时socket会立即触发error信号。

对于第4-5种情况,此时socket会等待30s左右发送error信号。

对于第6种情况, 此时socket会发送disconnect信号,可以绑定相应的槽去处理服务器断开的情况。

2.心跳包的使用与实现

对于某些场景下,客户端与服务器断开后,需要立即知道连接状态并做相应的处理,而不是等待几十秒后才有信号通知。要实现这种功能,一种比较好的方法就是用心跳包来实现。

发送心跳包,即客户端每隔一段时间发送一条报文,报文不需要附带具体内容,只 需要让服务端知道这是一条心跳报文,并回发一条消息,客户端收到这条消息后,就得知其与服务器保持连接的状态。

下面将心跳的代码实现示例出来,以便参考。这里会单独写一个心跳类TcpHeart。

//这是TcpHeart的头文件#ifndef TCPHEART_H#define TCPHEART_H

#include #include

class TcpHeart:public QObject

{

Q_OBJECT

public:

TcpHeart(QObject *parent = 0)

~TcpHeart(void);

void StartHeartTimer();

signals:

void SigHeartBad();

void SigHeartReq();

private slots:

void SlotTimeout();

void SlotHeartBack();

private:

QTimer *m_heart_timer;

int m_count;

};

#endif

//这是TcpHeart的实现文件

#include "tcpheart.h"

TcpHeart::TcpHeart(QObject *parent):QObject(parent)

{

m_heart_timer = new QTimer(this);

m_count = 0;

connect(m_heart_timer, SIGNAL(timeout()), this, SLOT(SlotTimeout()));

}

TcpHeart::~TcpHeart(void)

{

}

void TcpHeart::StartHeartTimer()

{

m_heart_timer->start(2000);

}

void TcpHeart::SlotTimeout()

{

if(m_count > 2)

{

m_count = 0;

m_heart_timer->stop();

emit SigHeartBad();

return;

}

m_count++;

emit SigHeartReq();

}

void TcpHeart::SlotHeartBack()

{

m_count = 0;

}

在客户端,当连接成功服务器后,启动心跳定时器:heart->StartHeartTimer(); 实现其socket的读写函数如下:

void SlotHeartReadyRead()

{

QByteArray heart_bytes = heart_socket->readAll();

if(QString(heart_bytes)== "OK") //连接成功从服务端读取OK字符 {

heart = new TcpHeart;

//开始心跳请求 heart->StartHeartTimer();

connect(heart, SIGNAL(SigHeartReq()), this, SLOT(SlotWriteHeartSocket()));

connect(this, SIGNAL(SigHeartBack()), heart, SLOT(SlotHeartBack()));

//掉线后的处理 connect(heart, SIGNAL(SigHeartBad()), this, SLOT(SlotHeartBad()));

}

//心跳反馈 if(QString(heart_bytes) == "HEART_BACK")

emit SigHeartBack();

}

void SlotHeartBad()

{

qDebug()<

//可以添加心跳失败的处理}

void SlotWriteHeartSocket()

{

heart_socket->write("HEART");

}

在服务器端,当有新的客户端连接成功后,直接向客户端写OK心跳字符,即heart_socket->write("OK"),并启动相应的定时器。其实现读取socket的函数如下:

void SlotReadHeartSocket()

{

QByteArray bytes = heart_socket->read(5); //注意这里要读取5个字节,而不是随意读取 if(QString(bytes) == "HEART")

{

heart_socket->write("HEART_BACK");

heart_count = 0;

}

}

本文到此结束!

如果对你有帮助,请随手 点个赞 或 点喜欢! 收藏不点赞,感觉不仁道......

=======================================================

欢迎【关注作者、私信作者】。我们一起交流一起进步。

=======================================================

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以通过在客户端和服务器端之间定期发送心跳包来检测QT qTcpsocket的连接状态。具体实现方法如下: 1. 客户端和服务器端约定一个心跳包的内容和发送周期,一般是发送一个长度为0的数据包。 2. 在客户端和服务器端分别使用器,定期发送心跳包。 3. 在客户端和服务器端分别设置超间,如果在超间内没有收到心跳包,则认为连接已断开。 4. 如果连接断开,则需要重新建立连接。 以下是一个简单的示例代码,用于在QT qTcpsocket实现心跳包的检测: ```c++ // 客户端发送心跳包 void Client::sendHeartbeat() { QByteArray heartBeatData; // 心跳包内容 m_tcpSocket->write(heartBeatData); } // 服务器端发送心跳包 void Server::sendHeartbeat(QTcpSocket* socket) { QByteArray heartBeatData; // 心跳包内容 socket->write(heartBeatData); } // 客户端检测心跳包 void Client::checkHeartbeat() { if (m_lastHeartbeatTime.elapsed() > HEARTBEAT_INTERVAL) { // 超断开连接 m_tcpSocket->disconnectFromHost(); } } // 服务器端检测心跳包 void Server::checkHeartbeat(QTcpSocket* socket) { if (m_socketHeartbeatMap.contains(socket)) { QDateTime lastHeartbeatTime = m_socketHeartbeatMap.value(socket); if (lastHeartbeatTime.msecsTo(QDateTime::currentDateTime()) > HEARTBEAT_INTERVAL) { // 超断开连接 socket->disconnectFromHost(); } } } // 客户端接收心跳包 void Client::onReadyRead() { m_lastHeartbeatTime.restart(); // 处理接收到的数据 } // 服务器端接收心跳包 void Server::onReadyRead(QTcpSocket* socket) { m_socketHeartbeatMap.insert(socket, QDateTime::currentDateTime()); // 处理接收到的数据 } ``` 在上面的示例代码,`HEARTBEAT_INTERVAL`代表心跳包发送的周期,可以根据实际情况进行调整。`m_lastHeartbeatTime`和`m_socketHeartbeatMap`分别记录客户端和服务器端最后一次接收到心跳包间。当超过心跳包发送周期没有接收到心跳包,就认为连接已断开

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值