0

現在、C++で透過的なHTTPプロキシを構築する方法を学んでいます。プロキシクライアント側には、長い間解決できなかった2つの問題がありました。次のシナリオに基づいて、誰かが根本的な原因を指摘できることを願っています。どうもありがとう。:D

私が今構築したHTTPプロキシは、どういうわけか部分的にしか機能しません。たとえば、キーワードを入力した後、検索結果を取得できなかったときに、プロキシを介してGoogleのメインページにアクセスできました(Googleインスタントもまったく機能していません)。一方、YouTubeは、検索、動画の読み込み、コメントなど、完璧に機能しています。さらに、yahooのようないくつかのWebサイトでは、URLを入力した後もメインページを表示できませんでした。

最初に問題がプロキシクライアント側にあると言ったのは、プログラムのデータフローを追跡したためです。ソケットプログラミング関数write()によって返される書き込みサイズが、ライトバック関数に渡したデータサイズよりも小さいことがわかりました。私にとって最も奇妙な観察は、データ損失の問題がデータのサイズとは無関係であるということでした。ソケットのwrite()関数は、2MB近くのYouTubeビデオデータに対しては適切に機能しますが、わずか20KBのGoogle検索リクエストのデータは失われます。

さらに、ライトバック関数に渡したデータサイズとソケット書き込み関数()によって返される書き込みサイズが同じである場合に、ブラウザーが空白で表示されるという別の状況もありました。私はwiresharkを使用して通信の流れを追跡し、プロキシを使用しない純粋なIP通信と比較しました。純粋なIP通信フローと比較して、特定のHTTP応答を受信した後、ブラウザーがHTTP要求を継続的に送信しないことがわかりました。ブラウザが残りのHTTPリクエストを送信しなかった理由がわかりませんでした。

以下は、ライトバック関数のコードです。

void Proxy::get_data(char* buffer, size_t length)
{
    cout<<"Length:"<<length<<endl;

    int connfd;
    size_t ret;

    // get connfd from buffer
    memset(&connfd, 0, sizeof(int));
    memcpy(&connfd, buffer, sizeof(int));
    cout<<"Get Connection FD:"<<connfd<<endl; 

    // get receive data size
    size_t rData_length = length-sizeof(int);
    cout<<"Data Size:"<<rData_length<<endl;
    // create receive buffer
    char* rBuf = new char[rData_length];
    // allocate memory to receive buffer
    memset(rBuf, 0, rData_length);
    // copy data to buffer
    memcpy(rBuf, buffer+sizeof(int), rData_length);

    ret = write(connfd, rBuf, rData_length);

    if(ret < 0)
    {
        cout<< "received data failed"<< endl;
        close(connfd);
        delete[] rBuf;
        exit(1);
    }
    else
    {
        printf("Write Data[%d] to Socket\n", ret); 
    }

    close(connfd);
    delete[] rBuf;    
}
4

2 に答える 2

0

あなたはこれを試すことができるかもしれません

int curr = 0;
while( curr < rData_length ) {
    ret = write( connfd, rBuf + curr, rData_length - curr );
    if( ret == -1 ) { /* ERROR */ }
    else
        curr += ret;
}

それ以外の

ret = write(connfd, rBuf, rData_length);

一般に、によって書き込まれるバイト数は、write()書き込みを要求したものとは異なる場合があります。マニュアルを読んだほうがいいです。たとえば、http://linux.die.net/man/2/write

于 2012-09-26T07:33:57.707 に答える
0

入力ソケットと出力ソケットの間でバイトをコピーするのは、これよりもはるかに簡単です。最後の読み取りによって読み取られたデータの量に応じて、バッファーを動的に割り当てる必要はありません。char[] 配列を読み取り、その配列からターゲットに書き込む必要があるだけです。読み取りによって返される長さの値を十分に考慮してください。

于 2012-09-26T09:57:18.750 に答える