长连接: 指在一个TCP连接上可以连续发送多个数据包,
在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接;
一般需要自己做在线维持。
//http长连接的使用
//m_pSimpleHttp = new SimpleHttp(HTTP_KEEPALIVE,this);//长连接类型 的http请求------------------- NetWorkCommunication中创建一个SimpleHttp的实例
//该m_pSimpleHttp维持 http长连接
//普通http请求的使用,非长连接
//NetworkCommunicate类中, m_pGetMsgHttp = new SimpleHttp(HTTP_POST,this);
//不管是长连接的http实例,还是非长连接的http实例,都是在NetWorkCommunication的析构函数中才会析构掉
//长连接和其他链接,没什么区别,长连接是个httpManager对象,该对象和服务器进行链接,
//服务器每隔15秒就向 该http链接中发送一个数据(心跳包), 客户端如果45s后,还没有收到 服务端发送过来的心跳包,那么客户端就主动关闭该http链接,
//非长连接,45s后,直接关闭掉该http连接,
enum HTTP_MODE
{
HTTP_GET = 0,
HTTP_POST,
HTTP_DOWNLOADFILE,
HTTP_UPLOADFILE,
HTTP_KEEPALIVE
};//http请求的类型 get post downloadfile uploadfile等
SimpleHttp* HttpRequestManage::addKeepAlivePost(TASK_PARAM * pTask)
{
KeepAliveTask* pKeepAliveTask = dynamic_cast<KeepAliveTask*>(pTask);
if(!pKeepAliveTask)
return NULL;
SimpleHttp* pHttp = new SimpleHttp(HTTP_KEEPALIVE, this);//标识 该请求为长连接请求---------------------
pHttp->setOutTimer(pKeepAliveTask->m_OutTimer);
pHttp->setPostRequestParam(pKeepAliveTask->m_strParam);
pHttp->setRecvMsgFunc(pKeepAliveTask->m_RecvMsgFunc);
pHttp->SetAtOnce(pKeepAliveTask->m_bAtOnce);
pHttp->httpRequest(pKeepAliveTask->m_strUrl, pKeepAliveTask->m_CompleteFunc);
return pHttp;
}
//开始做任务 执行http请求
void SimpleHttp::startRequest()
case HTTP_KEEPALIVE:
{
connect(m_spHttp.data(), SIGNAL(finished(QNetworkReply*)), this, SLOT(httpFinished(QNetworkReply*)));
QNetworkRequest request(m_Url);
QByteArray param;
if(m_PostParam.isEmpty())
param = m_Url.encodedQuery();
else
param.append(m_PostParam);
if(!m_Headers.isEmpty())
{
for(int i=0; i<m_Headers.size(); ++i)
{
QPair<QNetworkRequest::KnownHeaders, QVariant> pair = m_Headers[i];
request.setHeader(pair.first, pair.second);
}
}
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
m_NetworkReply = m_spHttp->post(request, param);
connect(m_NetworkReply, SIGNAL(readyRead()), this, SLOT(OnRecvMsg()));//http请求 已经返回数据了------------------ 对获取到的长连接请求的返回数据进行处理
connect(m_NetworkReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(httpError(QNetworkReply::NetworkError)));
}
if(m_OutTime < 0 && m_Mode == HTTP_KEEPALIVE )
{
m_OutTime = HEARTBEAT_TIME; //这个超时来处理心跳包
if(!m_AutoBreakOutTimer)
{
m_AutoBreakOutTimer = new QTimer(this);
connect(m_AutoBreakOutTimer, SIGNAL(timeout ()), this, SLOT(OnAutoBreakOutTimer()));
}
else
{
m_AutoBreakOutTimer->stop();
}
m_AutoBreakOutTimer->start(AUTO_BREAK_TIME); //长连接使用
}
m_OutTimer->start(m_OutTime);
//定时器的超时响应函数
/*
服务端每隔15秒发一次心跳包
//长连接请求发出后,该定时器设定为45秒后触发
//下面槽的作用,就是为了检测m_bRecvHeartbeat的值,即客户端是否收到了服务端发过来的心跳包
*/
void SimpleHttp::OnOutTimer()
{
//定时器超时了
m_bOutTime = true;
if(m_Mode != HTTP_KEEPALIVE)
{
m_OutTimer->stop();
}
else
{
//http是长连接
//开始检查心跳包
// 因为服务器每隔15s就发送一次心跳包
//如果45s还没有收到心跳包,那么说明连接中断了,
if(!m_bRecvHeartbeat) //心跳包停止了
{
m_OutTimer->stop();
m_AutoBreakOutTimer->stop();
m_NetworkReply->close();//没有收到心跳包,关闭http连接 //-------------------------------------长连接和短链接的根本的区别
}
else
{
//接收到了服务端发过来的心跳包,那么不关闭http连接
m_bRecvHeartbeat = false;
}
}
}
//第一步
//网络连接 NetrokCommunicate类,使用的就是http长连接。
//只使用了这一中连接http连接方式。
NetworkCommunicate::NetworkCommunicate(QObject *parent)
: QObject(parent)
, m_pSimpleHttp(NULL)
, m_pGetMsgHttp(NULL)
, m_Timer(NULL)
, m_nRequestNum(0)
, m_bPullMsg(true)
, m_nRetryTimes(0)
{
m_pSimpleHttp = new SimpleHttp(HTTP_KEEPALIVE,this);//长连接类型 的http请求-------------