编写 web服务器远程查看 mysql数据
黄金春 1,杜娟娇 2
(1.广西中医学院 信息网络中心,广西 南宁 530001;2.广西中医学院一附院,广西 南宁 530001)
摘要:目前 linux服务器在网络上以其安全和稳定而得到了广泛的使用,同时 mysql数据库也以
安全和稳定成为了 linux服务器上使用最多的数据库。因此,如何从 web上动态的读取 mysql数据
库的数据就成为了 linux 服务器上使用最多的应用之一。虽然目前已有解决的办法,但其对机器的
要求比较高,提出一种利用 Qt4 类结合 C++技术编写专用 web 服务器,实现动态读取 mysql 数据
库的数据的简易办法。该方法同目前各种方法对比,对设备要求非常低且运行速度快,具有非常好
的实用性。
关键字:web服务器,qt4, http
一、引言
目前,在 Internet上 linux服务器以其安全和稳定而得到了广泛的应用,并且当前其上有非常多
的应用都使用到数据库系统,同时 mysql 数据库也以安全和稳定成为了在 linux 上使用最多的数据
库之一。因此如何从 web上远程查看 mysql数据就成为了最多的应用之一。目前通常做法是在 linux
上安装 apache 服务器(完成 web功能),然后安装 php软件,最后还要编写 php程序(完成 mysql
数据读取),才可实现 mysql 数据库的 web 远程查看。此方法对机器的要求较高,而且需要安装大
量的应用软件。因此本文提出一种利用 Qt4 类结合 C++技术编写专用 web 服务器,实现动态的读
取 mysql数据库的数据的简易办法。该方法同目前各种方法对比,对设备要求非常低且运行速度快,
具有非常好的实用性。
二、相关技术知识
1、Web服务器:web的含义是“万维网”(World Wide Web, 即WWW),是一个基于超文本的
信息查询工具,它的特点是提供非常友好的查询网络信息的接口。Web 服务器是和 WWW 相连接
的计算机,它能够以 web页面的形式提供在浏览器中显示的查询结果信息1。其基本工作原理是Web
服务器接到来自网络的客户机程序(通常为 IE 等浏览器)请求后,即完成指定的查询,并将查询
的结果通过 internet送回客户机浏览器里显示。
2、Qt 4:Qt是 Trolltech公司的一个产品。它是用于创建 linux下的图形程序最出色的工具包之
一, Qt是一个多平台的 C++图形用户界面应用程序框架。它提供给应用程序开发者建立图形用户
界面所需的所有功能。Qt 是完全面向对象的很容易扩展,并且允许真正地组件编程2。 并且 Qt 支
持一种称为信号和槽机制,此机制非常类似 windows系统的事件驱动,因此在编写 linux下交互程
序时非常简单。
在这里编写的Web服务器需要在 linux平台下运行,同时还要完成数据库连接,文本文件读取,
网络数据传送等功能,因此选择 Qt4软件。
3、Http协议:Http协议是当前 internet上最为流行的网络协议,Http协议是(Hypertext Transfer
Protocol 超文本传输协议)的简称,它主要完成浏览器和Web服务器间的对话以及事务处理。目前
使用的是 Http 1.1版本。3下面简要说明其工作原理。
Http协议是以发送和接收消息为其核心的,它有两类消息:用于浏览器的请求消息和用于Web
服务器的响应消息。无论哪种消息,都分为消息头和消息体两部分,消息头主要是反映相互通告对
方的一些具体信息。它一般都由消息的标题字段和字段值构成,标题字段和字段值之间用冒号“:”
隔开。如:
HOST: 210.36.99.200
明请求资源所在的主机地址是 210.36.99.200
消息头可以有多个标题字段和字段值,以告知更多的信息。其他字段和字段值的详细介绍在这
里不再说明,读者可以参考 RFC2068。第二部分是消息体。消息体才是通信的具体内容,它有多种
形式。对于浏览器来说可以是传递给服务器的数据,如:
ip=210.36.99.10&curpage=10&…… 表明填写表单后用 post 方式提交的内容: ip 是
210.36.99.10,还有 curpage是 10等等。
对于Web服务器来说,消息体就是返回给浏览器的内容,因此通常是 html文档,当然还可以是
其它形式的数据如对于图片就是图片的二进制数据等等。
三、设计与实现
设计思路,专用Web服务器主要是使用自设计的 Socket类接受并读取由浏览器发送的数据,然
后对数据进行一定的分析,最主要的是分析数据的 post部分即请求内容,然后服务器根据请求内容
对 mysql数据库进行连接和读取,获得数据后,把数据写为 html文档格式送回客户机。这样浏览器
就可以正确解析并显示数据了。
1.1 Socket 类的设计
Socket类是本程序中极其重要的一个类,该类完成 Socket的建立与数据的发送和接收。因为本
服务器需要能够同时接受多个连接请求,所以该类必须设计为可以接受多个连接的。在 Qt4里已经
实现了 tcp数据的发送和接收,主要使用 tcpsocket类,但是 tcpsocket类仅可以接受一个连接请求。
因此我们需要在该类的基础上自己设计一个 Socket类。
为了可以实现多连接,可以模拟 vb里的控件数组形式进行设计。也就是说自定义的类在除了包
含有 tcpsocket类为参数外还必须有个参数作为类似数组下标唯一标识符,以区分不同该类的实例。
因此该类的构造函数就可以设计为 hjcSocket( QTcpSocket *, int); 其中的 int参数就是作为类似数
组下标使用。在进行使用时,可以这样设计:
hjcSocket *tcpHjc[10];
tcpHjc[i]=new hjcSocket(tcpServer.nextPendingConnection(),i);
connect(tcpHjc[ci],SIGNAL(connHjc(int)),this,SLOT(showConn(int)));
……
i++;
这样多连接就可以实现了。
1.2 Mysql数据库分页的读取
Mysql 数据库是 linux 里使用的最多的数据库。它可以支持一个真正的多用户、多线程 SQL 数
据库服务器。它能处理与任何不昂贵硬件平台上提供数据库的厂家在一个数量级上的大型数据库,
但速度更快。在 Qt4里读取数据库是比较方便的,可以使用其提供的 QtSql 类解决。这设计不难在
此方面读者可以参考其他书籍。
在Web服务器里要设计的重点是如何实现数据库里的数据分页读取。我们知道在网络里读取数
据库时为了减少浏览器的等待时间,一般都把数据进行分页,以使数据量减少,这样就必须实现数
据库的分页读取。
在Mysql数据库中 select语句提供了 limit 子句可以完成分页功能。它的用法是在 limit子句取
1个或 2个数字参数,如果给定 2个参数,那么第一个指定要返回的第一行的偏移量,第二个指定
返回行的最大数目。 如:
Select * from ip limit 5,10 ; 说明:返回从第 6行开始到 15行为止的数据。
在分页时,关键点是如何知道总页数,和如何知道当前的页数,只有这些信息都清楚了以后,
分页才可以实现。在此可以使用简单的办法即使用 html 语言里的隐藏属性
反复发送解决。
示例代码如下:
1、先连接数据库
db=QSqlDatabase::addDatabase("QMYSQL3");
db. 类的属性的其它设置如:数据库名,登陆名,密码等
if(!db.open()) 打开连接
{
qmess(trUtf8("错误"),trUtf8("无法打开数据库。")); qmess函数是自定义函数主要信息显示
return false ;
}
return true;
2、设置读数据库使用的 sql语句,利用 found_rows()函数得到总页数。
sqlText="SELECT SQL_CALC_FOUND_ROWS, * FROM ipb order by enddate desc";
然后根据读取浏览器发送的当前页来设置 limit子句。
sqlText=sqlText+" limit "+QString::number(CintCurPage*CsPage.toInt())+","+Page;
query->clear();
bSu=query->exec(sqlText);
sqlText=”select found_rows() from ipb;
读取 sql的结果值就是总页数。
3、最后再读取 sql运行结果内容并且构造为 html语句即可
while (query->next())
{
aa=aa+"
"; 构造为 html语句
for(i=0;ivalue(i); 表的第 i个字段值
aa=aa+""; 构造为 html语句
aa=aa+aa1.toString();
aa=aa+" | "; 构造为 html语句
}
aa=aa+"
" 构造为 html语句
}
把 aa内容发送回浏览器就可以实现分页了。
1.3 如何实现 Http协议
实现 Http协议是 Web服务器设计的重点也是难点之一。实现协议总的来说就是使 Web服务器
看得懂浏览器发送的请求,并且做出正确的响应。
根据前面的介绍,Http 协议无论是请求还是应答其内容是跟一些具体的标题字段有关,因此在
进行分析浏览器的请求设计时重点是查看请求的 post 内容。post 内容在前面介绍过它类似
ip=210.36.99.10&CurPage=10&……。其主要就是读取分隔的数据,难度不大读者可以自己完成。
在进行响应设计时,比分析请求要复杂些,不但要把某些标题字段内容填写清楚,还要把需要
发送回浏览器的数据按照 html格式来构造,这样浏览器才可以正确显示出数据。
为了使构造 html 格式简单,可以把不需要交互的固定的部分预先写为一个具体的 html 文件,
这样在需要的时候就不再需要构造,只要把此文件读取出来,发送到浏览器即可。当然,如果在数
据是交互的情况下(比如读取数据库内容时),此方式就不合适了,为此,还必须设计利用程序代
码构造 html语句。
下面是两种形式的示例代码:
形式 1(固定文件)
首先构造需要响应的文件头(标题字段),编写为固定文件,如 200.txt
200.txt文件内容如下:
HTTP/1.1 200 OK
Content-Length: hjc200 //hjc200这个数据需要用真正的字节数替换,这样才可以正确响应。
Content-Type: text/html
Accept-Ranges: bytes
…… 其他固定必要的标题字段和字段值内容。
然后确定要响应内容(htm文件)
QString answerStr;
if((url.contains("hjc.htm"))) 如果请求的是 htm 文件,此文件为静态的,可以利用固定文件响
应。
{
answerStr=readfile("200.txt"); //200.txt 为 http200响应头的固定文件
answerStr+=readfile("hjc.htm"); //hjc.htm为 html固定响应文件
strfilesize=QString::number(filesize); //获得发送的总字节数,要正确响应必须字节正确
k=answerStr.indexOf("hjc200");
answerStr.replace(k,6,strfilesize); 用真正的字节数替换 hjc200
}
最后把 answerstr发送回浏览器即可。
此方式因为内容固定,速度快,但无法完成交互功能。
形式 2(有交互的动态的数据,响应要使用程序代码构造)
下面以数据库分页为例简单说明:
首先从 post数据里读取系列数据
if((url.contains("hjc.hsp"))) //请求的文件为动态。
{
qip=questForm(questData,"ip="); 从 post数据里读取数据 包括查询 ip 当前页数等
……
qcurPage=questForm(questData,"curPage=");
CintCurPage=qcurPage.toInt();
if(fromUrl=="hjc.htm")
{
CintCurPage=0; 如果为第一次请求,当前页是第 0页
……
if(questData.indexOf("uppage=")!=-1)
{
CintCurPage--; 如果是单击上一页的请求,当前页减 1
……
else
{
CintCurPage++; 如果是单击下一页的请求,当前页加 1
……
然后根据数据构造响应的 html语句。
fromStrHinden="
";
fromStrHinden+="
";
……
最后发送回浏览器即可。
四、后记
这样的设计实现比较简单,同其他方法比较,代码少,而且是编译后执行,速度非常快!效率
也非常高。因此非常适合于某些专业用途的场合。另外,如果以后需要添加服务器功能(比如上传
图片等)只要在响应部分添加适当的代码即可,对此不再说明。
1 VBScript 可视化程序设计 刘炳文 编著 清华大学出版社 北京 1999
2 Linux 软件
师(C语言)实用教程 刘加海 张益先 主编 科学出版社 北京 2007
3 Visual Basic 网络通信协议分析与应用实现 汪晓平 钟军 编著 人民邮电出版社 北京 2003
<<
/ASCII85EncodePages false
/AllowTransparency false
/AutoPositionEPSFiles true
/AutoRotatePages /All
/Binding /Left
/CalGrayProfile (Dot Gain 20%)
/CalRGBProfile (sRGB IEC61966-2.1)
/CalCMYKProfile (U.S. Web Coated \050SWOP\051 v2)
/sRGBProfile (sRGB IEC61966-2.1)
/CannotEmbedFontPolicy /Warning
/CompatibilityLevel 1.4
/CompressObjects /Tags
/CompressPages true
/ConvertImagesToIndexed true
/PassThroughJPEGImages true
/CreateJDFFile false
/CreateJobTicket false
/DefaultRenderingIntent /Default
/DetectBlends true
/DetectCurves 0.0000
/ColorConversionStrategy /LeaveColorUnchanged
/DoThumbnails false
/EmbedAllFonts true
/EmbedOpenType false
/ParseICCProfilesInComments true
/EmbedJobOptions true
/DSCReportingLevel 0
/EmitDSCWarnings false
/EndPage -1
/ImageMemory 1048576
/LockDistillerParams false
/MaxSubsetPct 100
/Optimize true
/OPM 1
/ParseDSCComments true
/ParseDSCCommentsForDocInfo true
/PreserveCopyPage true
/PreserveDICMYKValues true
/PreserveEPSInfo true
/PreserveFlatness true
/PreserveHalftoneInfo false
/PreserveOPIComments false
/PreserveOverprintSettings true
/StartPage 1
/SubsetFonts true
/TransferFunctionInfo /Apply
/UCRandBGInfo /Preserve
/UsePrologue false
/ColorSettingsFile ()
/AlwaysEmbed [ true
]
/NeverEmbed [ true
]
/AntiAliasColorImages false
/CropColorImages true
/ColorImageMinResolution 300
/ColorImageMinResolutionPolicy /OK
/DownsampleColorImages true
/ColorImageDownsampleType /Bicubic
/ColorImageResolution 300
/ColorImageDepth -1
/ColorImageMinDownsampleDepth 1
/ColorImageDownsampleThreshold 1.50000
/EncodeColorImages true
/ColorImageFilter /DCTEncode
/AutoFilterColorImages true
/ColorImageAutoFilterStrategy /JPEG
/ColorACSImageDict <<
/QFactor 0.15
/HSamples [1 1 1 1] /VSamples [1 1 1 1]
>>
/ColorImageDict <<
/QFactor 0.15
/HSamples [1 1 1 1] /VSamples [1 1 1 1]
>>
/JPEG2000ColorACSImageDict <<
/TileWidth 256
/TileHeight 256
/Quality 30
>>
/JPEG2000ColorImageDict <<
/TileWidth 256
/TileHeight 256
/Quality 30
>>
/AntiAliasGrayImages false
/CropGrayImages true
/GrayImageMinResolution 300
/GrayImageMinResolutionPolicy /OK
/DownsampleGrayImages true
/GrayImageDownsampleType /Bicubic
/GrayImageResolution 300
/GrayImageDepth -1
/GrayImageMinDownsampleDepth 2
/GrayImageDownsampleThreshold 1.50000
/EncodeGrayImages true
/GrayImageFilter /DCTEncode
/AutoFilterGrayImages true
/GrayImageAutoFilterStrategy /JPEG
/GrayACSImageDict <<
/QFactor 0.15
/HSamples [1 1 1 1] /VSamples [1 1 1 1]
>>
/GrayImageDict <<
/QFactor 0.15
/HSamples [1 1 1 1] /VSamples [1 1 1 1]
>>
/JPEG2000GrayACSImageDict <<
/TileWidth 256
/TileHeight 256
/Quality 30
>>
/JPEG2000GrayImageDict <<
/TileWidth 256
/TileHeight 256
/Quality 30
>>
/AntiAliasMonoImages false
/CropMonoImages true
/MonoImageMinResolution 1200
/MonoImageMinResolutionPolicy /OK
/DownsampleMonoImages true
/MonoImageDownsampleType /Bicubic
/MonoImageResolution 1200
/MonoImageDepth -1
/MonoImageDownsampleThreshold 1.50000
/EncodeMonoImages true
/MonoImageFilter /CCITTFaxEncode
/MonoImageDict <<
/K -1
>>
/AllowPSXObjects false
/CheckCompliance [
/None
]
/PDFX1aCheck false
/PDFX3Check false
/PDFXCompliantPDFOnly false
/PDFXNoTrimBoxError true
/PDFXTrimBoxToMediaBoxOffset [
0.00000
0.00000
0.00000
0.00000
]
/PDFXSetBleedBoxToMediaBox true
/PDFXBleedBoxToTrimBoxOffset [
0.00000
0.00000
0.00000
0.00000
]
/PDFXOutputIntentProfile ()
/PDFXOutputConditionIdentifier ()
/PDFXOutputCondition ()
/PDFXRegistryName ()
/PDFXTrapped /False
/Description <<
/CHS
/CHT
/DAN
/DEU
/ESP
/FRA
/ITA
/JPN
/KOR
/NLD (Gebruik deze instellingen om Adobe PDF-documenten te maken voor kwaliteitsafdrukken op desktopprinters en proofers. De gemaakte PDF-documenten kunnen worden geopend met Acrobat en Adobe Reader 5.0 en hoger.)
/NOR
/PTB
/SUO
/SVE