最近的一个项目需要用qt写一个http的服务器,之前做过http的客户端,客户端很简单,网上一搜一大堆。服务器还是第一次做,网上找资料说有个大牛写了个JQHttpServer,而且是开源的,就再github上下载下来了,很完整的源码,还有demo,感谢这个好心人。
但使用的时候我想的到session里面的信息,发现没有这个信号,就想QTcpSocket里面那样直接有个onRedReady()信号给我们用,让我们在客户端发信息的瞬间得到客户端发过来的消息,那么没有咋办呢,首先想到的是个笨办法,把那个回调写到一个线程里,然后不然run()函数结束,在类里定义个静态的队列,将客户端的消息塞进队列,然后扫描队列将信息用信号的方式发出来。
方法一:
void Kthread::run()
{
JQHttpServer::TcpServerManage tcpServerManage( 2 ); // 设置最大处理线程数,默认2个
tcpServerManage.setHttpAcceptedCallback( []( const QPointer< JQHttpServer::Session > &session )
{
session->replyText(QString("Whatever you ask, I'll only respond to sb"));
QString str = session->requestBody();
Kthread::m_queue.enqueue(str);
} );
qDebug() << "listen:" << tcpServerManage.listen( QHostAddress::Any, 23412 );
while(1)
{
while(!m_queue.isEmpty())
{
QString str = m_queue.dequeue();
emit onRedReady(str);
}
msleep(20);
}
}
方法二:
后来想想老觉得这样不合适,太浪费资源了,而且本来Http传来传去就慢,这样更慢了,后来就想到去源码看看,后来在 TcpServerManage: public AbstractManage 里面定义了一个信号,在客户端session过来的瞬间发出来,
void JQHttpServer::AbstractManage::handleAccepted(const QPointer<Session> &session)
{
QtConcurrent::run( handleThreadPool_.data(), [ this, session ]()
{
if ( !this->httpAcceptedCallback_ )
{
qDebug() << "JQHttpServer::Manage::handleAccepted: error, httpAcceptedCallback_ is nullptr";
return;
}
this->httpAcceptedCallback_( session );
Session *a = qobject_cast<Session*>(session);
if(a != nullptr)
emit onRedReady(a->requestBody());
} );
}
然后在主线程里链接起来
ht = new JQHttpServer::TcpServerManage(2);
connect(ht,&JQHttpServer::TcpServerManage::onRedReady,this,&MainWindow::onReply);
ht->setHttpAcceptedCallback( []( const QPointer< JQHttpServer::Session > &session )
{
session->replyText(QString("Whatever you ask, I'll only respond to sb"));
} );
qDebug() << "listen:" << ht->listen( QHostAddress::Any, 23412 );
经测试,是可以的,不知道大家有没有更好更合适的方式!