我是靠谱客的博主 认真香氛,这篇文章主要介绍QT下用代码在程序内部搭建一个简单的HTTP协议服务器,现在分享给大家,希望可以做个参考。

最近使用一个第三方PDF控件,此控件提供的一个打开文件方法只能支持http和https协议,所以没办法加载本地文件,最后试了半天各种方案,决定在程序内部启动一个简单的http服务器。

原理很简单利用传输层的TCP协议,模拟HTTP协议。

首先搞清http是如何加载网络文件的,方法很简单,在浏览器里面打开一个文件(我这是需求是PDF类型),然后用抓包工具看返回数据格式:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
HTTP/1.1 200 OK Content-Type: application/pdf Last-Modified: Mon, 08 Dec 2014 08:58:40 GMT Accept-Ranges: bytes ETag: "9516d29c512d01:0" Server: Microsoft-IIS/7.5 X-Powered-By: ASP.NET Date: Mon, 02 Nov 2015 08:34:34 GMT Content-Length: 545923 %PDF-1.5 %µµµµ 1 0 obj <</Type/Catalog/Pages 2 0 R/Lang(zh-CN) /StructTreeRoot 38 0 R/MarkInfo<</Marked true>>>> endobj 2 0 obj

这是一个简单的http协议,不是所有项都需要,只要模拟下面几项就可以了

1.HTTP/1.1 200 OK

2.Content-Type: application/pdf

3.Accept-Ranges: bytes

4.Content-Length:  545923

5.文件二进制数据


下面是代码:

httpSvr.h

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#pragma once #include <QCoreApplication> #include <QNetworkInterface> #include <iostream> #include <QObject> #include <QTcpSocket> #include <QTcpServer> #include <QDebug>   #define PORT 61301 // TCP 端口1 class  httpSvr : public QObject {     Q_OBJECT public:     explicit httpSvr(QObject *parent = 0);     ~httpSvr();     QTcpSocket *socket;     int port(); public slots:     void myConnection();     void readMessage(); private:     QTcpServer *server;     int _port; signals: };

httpSvr.cpp

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "httpSvr.h" #include <QFile> #include <QChar> using namespace std; httpSvr::httpSvr(QObject *parent) : QObject(parent) { socket = 0; // 客户端socket server = new QTcpServer(this); connect(server, SIGNAL(newConnection()),this, SLOT(myConnection())); qDebug()<< "httpSvr start listen, port:"<< PORT; if(server->listen(QHostAddress::Any, PORT)) {     qDebug()<<"success";         } else {      qDebug()<<"failed"; } } int httpSvr::port() { return PORT; } void httpSvr::readMessage(){ QString readmsg = socket->readAll(); //GET /J%3A%2Fmyclient%2Fmyclient%2FZB%2F2015_10_24_20_18_44%2FGC%2FZBWJ.pdf HTTP/1.1 // 通过URL取文件路径,具体看下面说明 QStringList msgList = readmsg.split('n'); QString getURL = msgList.first().toUpper(); getURL.replace("GET /", ""); getURL.replace(" HTTP/1.1", ""); getURL.replace("r", "").replace("n", ""); getURL.trimmed(); //URL解码 QByteArray ba; QString getPath = ba.fromPercentEncoding(getURL.toUtf8());  QFile f(getPath);   if(!f.open(QIODevice::ReadOnly | QIODevice::Unbuffered))  { socket->disconnectFromHost(); return; }  QByteArray barr = f.readAll(); f.close(); // 模拟http协议 QString lens(QString::number( barr.length())); socket->write("HTTP/1.1 200 OKrn"); socket->write("Content-Type: application/pdfrn"); socket->write("Accept-Ranges: bytesrn"); QString sLen("Content-Length: "+lens+"rnrn"); socket->write(sLen.toLatin1()); socket->write(barr); socket->flush(); connect(socket, SIGNAL(disconnected()),socket, SLOT(deleteLater())); socket->disconnectFromHost(); } void httpSvr::myConnection() {     socket = server->nextPendingConnection();     if (socket) {         connect(socket, SIGNAL(disconnected()),socket, SLOT(deleteLater()));         connect(socket,SIGNAL(readyRead()),this,SLOT(readMessage())); //有可读的信息,触发读函数槽     } } httpSvr::~httpSvr() { if (socket) socket->close(); }

上面主要看readMessage方法,流程是解析http请求,获取要加载的文件路径,然后读取文件二进制数据,模拟http数据报文,通过socket发出即可。

http服务如何知道读取哪个文件呢?这地方我是通过URL来传递的,将带加载的文件的全路径,通过URL编码后拼接在URL请求后面,httpsvr解析请求,通过解码获取文件路径,再加载即可。

启动服务:

复制代码
1
2
httpSvr *server; //全局的 server = new httpSvr();

调用方法:

复制代码
1
2
3
4
QString path = "d:/myclient/myclient/abc.pdf"; QString baPath = path.toUtf8().toPercentEncoding(); QString openUrl = QString("http://127.0.0.1:61301/%1").arg(baPath); myCtrl.OpenUrl(openUrl);// 我的第三方控件调用方法

因为是本机,所以http的地址是127.0.0.1, 后面端口号是服务里面定义的端口号。然后将待加载的文件路径编码后拼接在地址后面。

也可以直接在浏览器里面打开openUrl地址,直接看到效果。

转载于:https://my.oschina.net/u/2492458/blog/524946

最后

以上就是认真香氛最近收集整理的关于QT下用代码在程序内部搭建一个简单的HTTP协议服务器的全部内容,更多相关QT下用代码在程序内部搭建一个简单内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部