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* 并且该函数将分配正确的内存量(在运行时根据主机和返回的字节数确定) recv(). 无论如何,我是否可以从内存中的字符串流作为 char 数组获取永久副本,并且在函数返回并且字符串流超出范围后指针变坏?

[编辑]:下面是我的问题中发布的解决方案,任何希望将其重用于 Winsock2 编程的人都可以使用它,似乎效果很好。当 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

resphttp_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::stringand boost::asio,您将不再遇到内存管理问题。

于 2012-05-17T00:42:05.457 回答