0

Winsock2 を使用して HTTP プロトコルを試しています。私は機能に取り組んでいます

int recv_data(const char *hostname, char *resp);

この関数は、特定のホストに HTTP HEAD リクエストを送信し、レスポンスを受信することを目的としています。ポインター resp にメモリを割り当て、そこに応答をコピーしてから、受信した応答の合計バイト数を返します。

これが私の受信ループです:

int recv_data(const char *hostname, char *resp)
{
    int totalRecvd = 0;
    stringstream sStream;
    while (true)
    {
        char buffer[MAX_HEADER_SIZE];
        int retValue = recv(s, buffer, MAX_HEADER_SIZE, 0);
        if (retValue == 0)
            break;  // connection has been closed
        else if (retValue == SOCKET_ERROR)
            throw RecvException("http_headreq() unable to receive data");
        else    //
        {   
            buffer[retValue] = 0; // append null terminator
            sStream << buffer;    // dump buffer into stream
            totalRecvd += retValue + 1; // tally received bytes
        }
    }

    /** Allocate and read entire read stream into memory */
    resp = new char[totalRecvd + 1];
    strcpy(resp, sStream.str().c_str());
    return totalRecvd);
}

これはすべて正常に機能し、この時点で resp を出力すると、正常に出力されます。関数が明らかに戻った後に resp を出力しようとすると、問題が発生します。これが通常のやり方であるとは思いません。もし私が間違っていなければ、stringstream を使用して応答を一時的に保存することに関係があると思います。stringstream が収集するデータが範囲外になることについてどこかで読んだことがあると思います。

この関数をこのように設定して、呼び出し元が char* を渡すだけで、関数が正しい量のメモリを割り当てることができることを期待していました (これは、ホストとによって返されるバイト数に応じて実行時に決定されます)。関数が戻り、stringstream が範囲外になった後、ポインターが不良である char 配列として、メモリ内の stringstream から永続的なコピーを取得する方法はありますか?

[編集]: これが私の問題に組み込まれた以下に投稿された解決策です。これを Winsock2 proramming に再利用しようとしている人は誰でもうまくいくようです。recv() が 0 を返すと、接続が閉じられるまでサーバーからデータを受信します。 new 演算子がポインターを変更し、渡されない限り、関数が戻った後にその変更が反映されないため、ソリューションはポインターへの参照を渡します。参考までに。

int recv_data(SOCKET s, char *&data)
{
    int totalRecvd = 0;
    std::stringstream sStream;
    while (true)
    {
        char buffer[MAX_HEADER_SIZE];
        int retValue = recv(s, buffer, MAX_HEADER_SIZE, 0);
        if (retValue == 0)
            break;  // connection has been closed
        else if (retValue == SOCKET_ERROR)
            throw RecvException("http_headreq() unable to receive data");
        else    //
        {   
            buffer[retValue] = 0; // append null terminator
            sStream << buffer;    // dump buffer into stream
            totalRecvd += retValue + 1; // tally received bytes
        }
    }

    /** Allocate and read entire read stream into memory */
    data = new char[totalRecvd + 1];
    strcpy_s(data, totalRecvd, sStream.str().c_str());
    data[totalRecvd] = 0;
    return totalRecvd;
}
4

2 に答える 2

3

resp関数内のローカル変数ですhttp_req。の値を更新してrespも、以外の効果はありませんhttp_req。この行:

resp = new char[totalRecvd + 1];

ローカル効果のみがあります。

この署名を試してください:

int http_req(const char *hostname, char *&resp);


さらに良いことに、C++の方法でデータを返すようにしてください。

std::string http_req(const std::string& hostname) {
    ...
    return sStream.str()
}
于 2012-05-17T00:27:54.950 に答える
0

と を使用するようにコードを変更するstd::stringboost::asio、メモリ管理の問題に悩まされることはなくなります。

于 2012-05-17T00:42:05.457 に答える