2012-05-27 183 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

相關問題