赞
踩
实现这个功能我们需要继承重写两个类,一个是线程QThread,一个是Tcp Server,线程是为了把数据通信和主线程分开,避免阻塞,Tcp Server就不用说了,用来应答浏览器及数据通讯。
我们可以先看头文件,两个类:
- class HttpSendThread : public QThread
- {
- Q_OBJECT
- public:
- HttpSendThread(QObject *parent = nullptr):QThread(parent)
- {
- }
- ~HttpSendThread(){}
- void SetParameters(qintptr socketDescriptor);
- void run();
- qintptr m_socketDescriptor;
-
- protected slots:
- void sockdisconnect();
- private:
- bool m_isRunning;
- QTcpSocket *m_socket = nullptr;
- };
-
- class MyTcpServer : public QTcpServer
- {
- Q_OBJECT
-
- public:
- MyTcpServer (QObject *parent = 0);
- ~MyTcpServer ();
- qintptr m_socketDescriptor;
- bool status();
- protected:
- void incomingConnection(qintptr socketDescriptor) ;
-
- private:
- HttpSendThread *m_httpsendthread = nullptr;
-
- };
在这里介绍一下两个函数:
MyTcpServer中的void incomingConnection(qintptr socketDescriptor) :
这个函数是当tcpserver被连接时触发的槽函数,重写这个函数主要是为了获得socketDescriptor这个描述符
HttpSendThread中的void SetParameters(qintptr socketDescriptor):
这个函数就是用来传递socketDescriptor描述符,使得线程中能够使用socket进行和浏览器通讯,具体可以看下面的实现过程。
cpp文件:
首先是MyTcpServer的函数实现(构造函数可忽略):
- //当浏览器通过输入IP:PORT进入时,该函数被调用
- void MyTcpServer::incomingConnection(qintptr socketDescriptor)
- {
- qDebug() << "[OutputPackage]Browser request connection";
-
- if (!m_httpsendthread )
- {
- m_httpsendthread = new HttpSendThread();
- }
-
- if(!m_httpsendthread->isRunning())
- {
- m_socketDescriptor = socketDescriptor;
-
- //传递描述符
- m_httpsendthread->SetParameters(m_socketDescriptor);
- m_httpsendthread->start();
- }
-
- }
然后是 HttpSendThread类:
- void HttpSendThread::SetParameters(qintptr socketDescriptor)
- {
- m_socketDescriptor = socketDescriptor;
-
- }
-
- void HttpSendThread::run()
- {
- if(m_socket== nullptr)
- {
- qDebug() << "Socket init.";
- m_socket= new QTcpSocket;
- if (!m_socket->setSocketDescriptor(m_socketDescriptor)) {
- return;
- }
- connect(m_socket,SIGNAL(disconnected()),this,SLOT(sockdisconnect()));
- }
-
- //到这里,这个线程的run函数就可以正常使用这个m_socket去通信啦
- //do something...
-
- }
在run函数中,我们就可以按照http的协议给浏览器返回应答信息啦。
例如:
- //这里是http的协议应答头
-
- QString http = "HTTP/1.1 200 OK";
- http += QString("Content-Type: text/html; charset=utf-8\r\n\r\n");
-
- //这里是一些网页布局html5+javascript
-
- QString httphtml = QString("<head >");
- httphtml += QString("<title >luguosheng0110</title>");
- httphtml += QString("<p id='time' align='right'>time</p>");
- httphtml += QString("<center>");
- httphtml += QString("<h1> LUGUOSHENG</h1>");
- httphtml += QString("</center>");
-
- httphtml += QString("<style type='text/css'>");
- httphtml += QString(".image{");
- httphtml += QString("float:left;width:50%;margin-top:5%;margin-left:2%;}");
- httphtml += QString(".text{");
- httphtml += QString("border: solid #87CEFA;");
- httphtml += QString("height: 570;");
- httphtml += QString("border-width: 1px;");
- httphtml += QString("background: #F0FFFF;");
- httphtml += QString("float:right;width:45%;margin-top:5%;}");
- httphtml += QString("</style>");
-
- httphtml += QString("</head>");
-
- httphtml += QString("<div class='text'>");
- httphtml += QString("<center>");
-
- httphtml += QString("<h3><p id='t1'>The content you selected will be displayed</p></h3>");
- httphtml += QString("</center>");
- httphtml += QString("</div>");
-
- httphtml += QString("<div id = 'div1' class = 'image' style = 'width:48% ;'>");
-
- //重点留意一下这里,下面会继续讲
- httphtml += QString("<img id = 'p1' src = 'data:image/jpg;base64,%1' width = '100%' alt = 'After the camera captures, the screen will be displayed (or the current device is occupied)' />").arg(qhexed);
-
- httphtml += QString("</div> ");
-
- //合并一起发给浏览器
- http += httphtml;
- m_socket->write(http.toUtf8());
那么发过去之后的效果是怎样的呢?看下面:
由于我没有加载图片数据,所以图片那里不能显示(在这里感谢菜鸟教程提供平台给我测试验证!)。
那么图片怎么显示呢?
这里介绍一下如何把QImage转换到某个数据类型,然后放在html5代码中一起发送到浏览器显示。
- httphtml += QString("<img id = 'p1' src = 'data:image/jpg;base64,%1' width = '100%' alt = 'After the camera captures, the screen will be displayed (or the current device is occupied)' />").
- arg(qhexed);
从这段代码可以看到,我是把图片数据放到qhexed中,然后放到QString中。
转换过程:
- QImage image;
- //把图片数据放到image中,该步省略。
-
- QByteArray ba;
- QBuffer buf(&ba);
- buf.open(QIODevice::WriteOnly);
- if (!image.save(&buf, "jpg", 6))
- {
- qWarning() << "Jpg image save to buf failed,imageformats folder is missing.";
- }
- QByteArray hexed = ba.toBase64();
-
- QString qhexed(hexed);
经过这段转换,QImage数据就转成了浏览器可以解析的base64格式了,放在qhexed中。
到这里,其实就可以在浏览器看到图像了。
然后,当你再次使用socket给浏览器发送html代码数据时,你会发现新数据会追加在下面,而不是在原来的位置刷新。这里就需要用到javascript+html5代码进行替换,比如:
- //文本更新:
- QString txtdata = "<script>'use strict';";
- txtdata += QString("function t1myTimer()");
- txtdata += QString("{");
- txtdata += QString("document.getElementById('time').innerHTML=Date();");
- txtdata += QString("document.getElementById('t1').innerHTML = null;");
-
- QString str_send = "new txt";
-
- txtdata += QString("document.getElementById('t1').innerHTML = decodeURIComponent(escape('%1'));").arg(str_send);
- txtdata += QString("}");
- txtdata += QString("t1myTimer();");
- txtdata += "</script>";
-
- //图像更新:
- QString imagedata= QString("<script>'use strict';");
- imagedata+= QString("function p1myTimer()");
- imagedata+= QString("{");
- imagedata+= QString("let element = document.getElementById('div1');");
- imagedata+= QString("let child = document.getElementById('p1');child.src = null;");
- imagedata+= QString("element.removeChild(child);");
- imagedata+= QString("let para = document.createElement('img');");
- imagedata+= QString("para.setAttribute('id','p1');para.setAttribute('width','100%');");
- imagedata+= QString("para.setAttribute('src','data:image/jpg;base64,%1');").arg(qhexed);
- imagedata+= QString("let element1 = document.getElementById('div1');");
- imagedata+= QString("element1.appendChild(para);");
- imagedata+= QString("}");
- imagedata+= QString("p1myTimer();");
- imagedata+= "</script>";
这样,新数据就会在同样的位置去刷新显示了。
然后,当你在浏览器按F12时,你就会发现html5代码会一直累加一直累加。
这里就需要用到<script>document.body.innerHTML = ' **** ';</script>进行整体替换,把最初的布局代码重新发一遍,就可以实现清空现有的网页代码。
由于实现过程比较复杂,所以我描述得也有点乱,如果你想实现,感觉还是需要不断测试。希望对你们有用~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。