2012-05-27 188 views
3

我正在寻找一种方法来访问&篡改由Qt应用程序发送和接收的原始数据包数据,但找不到任何东西。有什么方法吗? 或者如果不是,应用程序至少有一种方法来从QWebView访问分组数据。从Qt应用程序获取原始数据包数据

有没有什么方法可以实现上述任何一种?

+1

我不明白你的意思。你正在编写一个Qt应用程序,需要访问“原始数据包”吗?你的意思是什么“原始数据”? – Mat

+0

我的意思是说,我用QWebView制作了一个浏览器。现在,无论何时QWebView从互联网上下载/上传数据,我都想访问发送和接收的http数据包数据,并篡改它。可能吗? – Sam

+0

...和代理服务器呢?我在一个新的答案中解释得更好... –

回答

3

对不起,萨姆,我不能让它工作。我一直在尝试我能想象到的一切,但没有任何事情会像预期的那样。

让我们的选项的短名单,并能做什么和不能做:

  • 您可以通过获取QWebFramewebView->page()->currentFrame(),然后接入到方法,如setContents()的方式访问所检索的网页,setHtml()toHtml()toPlainText()。您可以通过这些功能动态更改小部件中显示的网页。

  • 您可以通过replyFinished()插槽中的方法reply->readAll()访问为每个请求接收到的原始响应(以字节数组形式)。

  • 通过覆盖您自己的网络访问管理器中的QNetworkAccessManager::createRequest()方法,可以拦截请求。您可以访问请求中发送的URL和标题,并更改它们或取消请求。

但是......你要访问的请求和回答数据每个请求。

访问请求很简单,它已被解释为自定义QNetworkAccessManager中的createRequest()方法。但是,让我们来谈谈其他部分:

  • 对于我所看到的,从请求得到的答复是只读的IT不能改变,因为它是在硬编码源代码为QNetworkReply

  • 不能使用writeData()功能QNetworkReply,因为它是硬编码简单地做return -1

  • 您可以尝试继承自己的QNetworkReply,然后将其返回到自定义QNetworkAccessManagercreateRequest()方法中。您必须覆盖功能readAll(),bytesAvailable()abort()。奇怪的是,这个方法只有在请求发送到非HTTP目的地时才起作用。我认为QNetworkAccessManager的内部调用QNetworkReply的不同实现取决于所使用的协议(HTTP,FTP,...)。所以这在某种意义上是有效的,但不是我们想要的方式。例如,此方法可用于在特定条件下返回预定义的网页。

  • 考虑到QNetworkAccessManager::createRequest()必须返回QNetworkReply对象的事实,我看不到允许在回复的字节数组中篡改的子类化的任何组合。它受到很好的保护,您必须重新实现这些类上的所有内容才能实现您的目标。几乎复制粘贴所有QtNetwork零件的源类并自行实施。

所以我认为,答案是:“不,似乎它不能完全按照自己的要求进行;只有部分”。

对不起。

+0

起初我以为这是一个简单的任务。我把我的话回来!无论如何,非常感谢Felix提供如此巨大的支持,并花费宝贵的时间帮助我(至少它帮助我清楚了解QNetworkAccessManager的工作原理)!我非常感谢你的帮助。 – Sam

+0

我发现API真的很难做自定义更改... – Jack

3

在网络连接中篡改与服务器之间发送/接收数据的正确方法是使用QNetworkAccessManager

这个类可以让你发送一个请求给服务器(可能带有头文件)并获得响应(也包含头文件)。

您可以访问相应的QNetworkReply对象上收到的数据。响应也标题:

{ 
    ... 
    QNetworkAccessManager *qnam = new QNetworkAccessManager(this); 
    connect(qnam, SIGNAL(finished(QNetworkReply*)), 
      this, SLOT(replyFinished(QNetworkReply*))); 

    QNetworkRequest request; 
    request.setUrl(QUrl("http://stackoverflow.com")); 
    request.setRawHeader("User-Agent", "Foo browser"); 
    qnam->get(QNetworkRequest(request)); 
    ... 
} 

然后定义槽:

void MyWidget::replyFinished(QNetworkReply *reply) 
{ 
    QByteArray response = reply->readAll(); 
    QString mime = reply->header(QNetworkRequest::ContentTypeHeader).toString(); 
    ... 
} 

看一看文档herehere

事实上,一个QWebView有一个QNetworkAccessManager对象来执行请求和管理回复。您可以通过QWebPage::networkAccessManager()方法获取该对象。您可以通过QWebView::page()QWebView获取QWebPage


编辑

要操纵由QWebView显示网页时,可以直接通过webView->setHtml(QString html)来设定一个新的HTML内容。

您也可以通过QWebFrame类的方法直接访问HTML。

为了获得这样的对象,你必须做到:

QWebFrame *wb = webView->page()->currentFrame(); 

的方法是:

  • void QWebFrame::setContent (const QByteArray & data, const QString & mimeType = QString(), const QUrl & baseUrl = QUrl())在字节数组设置一个新的文档。

  • ​​也是这样,但考虑到内容是一个HTML文档。

  • QString QWebFrame::toHtml() const以获取HTML文档的内容。

  • QString QWebFrame::toPlainText() const与上面相同,为纯文本。

查看这些功能的文档。


编辑2:

最后,如果要访问或过滤由QWebView自身提出的要求,我可以看到只有一条路:从QNetworkAccessManager派生类和覆盖所使用的方法提出请求并接收答案。

然后,将该类的实例设置为QWebView使用的QNetworkAccessManager。

让我有骨架澄清:

class MyNAM : public QNetworkAccessManager 
{ 
    // ... 

    MyNAM(QObject *parent = 0) : QNetworkAccessManager(parent) { } 

    // ... 

    virtual QNetworkReply * createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0) { 

    // e.g. logging of the request 

    // e.g. decide if the request must be made 
    if (some_bool_deciding) { 
     QNetworkAccessManager::createRequest(op, req, outgoingData); 
    } 
    else { 
     // or faked... 
    } 
    // etc. 
    } 

    // ... 
}; 

在主应用程序,你必须做:

// ... 
MyNAM *nam = new MyNAM(); 
webview->page()->setNetworkAccessManager(nam); 
// ... 

从现在开始,所有的请求都将使用该对象进行。

此方法允许完全控制导航器所做的请求:筛选和访问请求数据(标题,取值和后置值等)。您可以记录请求,分析请求和他们的POST/GET字段等。

希望终于有所帮助!

+0

所以这里是我做的 'QNetworkAccessManager * manager = ui-> webView-> page() - > networkAccessManager(); (经理,SIGNAL(完成(QNetworkReply *)),这个,SLOT(完成(QNetworkReply *))); void MainWindow :: finished(QNetworkReply * reply) { qDebug()< isWritable(); }' 从上面的代码中,isWritable()返回false,所以我不能编辑/追加收到的数据。那么对从QNetworkReply收到的数据进行编辑/追加的正确方法是什么? – Sam

+0

数据由slot函数内的'reply-> readAll()'返回。看看我的插槽功能。 'QByteArray'是原始响应(字节数组)。您可以根据需要操纵收到的“QByteArray”。 –

+0

是的,我可以但我想操纵QWebView显示的内容。即使我操纵槽功能中的回复,它也不会反映在QWebView中。 – Sam

0

...和代理服务器呢?一个良好的睡眠让我想到了这种可能性。

您可以在loopback exampletorrent client example之间创建一个。因此,您可以捕获和篡改请求的答复。

您可以使用webView->page()->networkAccessManager()->setProxy()在客户端QWebView上配置代理。

这涉及到建立一个进程来监听所需的端口(例如8080)并监听本地主机上的连接。

您必须实现代理的由协议:

  1. 分析GET和POST操作,
  2. 接收到完整的请求作为二进制传输,
  3. 刚柔并请求,
  4. 将连接中获得的请求发送到目标IP,
  5. 然后您可以捕获回复,
  6. Tam根据收到的回复,并且
  7. 将产生的响应发送到客户端webView。

在这里我没有经验,但路径似乎很清楚。这将是很多编码,但我认为这是一个很好的选择如果不是唯一选项

更重要的是:它可以做到

+0

当然,可以使用代理服务器来完成。我曾经想过,但我也认为它可以在QT应用程序本身内完成。但事实并非如此,所以这让我别无选择,只能使用代理服务器。谢谢! – Sam

相关问题