如何使用 C++ 将服务器的响应接收到字符串变量中?

How to receive the response of a server into a string variable using c++?

我正在使用带套接字的 C++ 编写控制台应用程序。我需要将响应接收到字符串中而不是字符数组中。问题是我不知道该怎么做。有人知道答案吗?感谢大家。

现在我有这个代码:

    char buffer[1000000];
    int nDataLength;
    while ((nDataLength = recv(Socket, buffer, 1000000, 0)) > 0) {
        int i = 0;
        while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
            cout << buffer[i];
            i += 1;
        }
    }

我需要在接收数据之前将 buffer 转换为字符串,因为如果我使用 char 数组,缓冲区不够大,无法存储 entaire 结果,如果我增加大小,Visual Studio 显示套接字初始化错误

我使用:

WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        cout << "WSAStartup failed.\n";
        system("pause");
        return 1;
    }
    SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    struct hostent *host;
    host = gethostbyname("www.site.com");
    SOCKADDR_IN SockAddr;
    SockAddr.sin_port = htons(80);
    SockAddr.sin_family = AF_INET;
    SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);

这是因为我需要将响应存储到字符串中的方式但是:我该怎么做?

你可以使用这个:

const std::ssize_t max_size = 1000000;
std::string buffer();
buffer.resize(max_size);

// and use where you need:
ssize_t new_size = recv(Socket, &buffer[0], max_size, 0);
buffer.resize (new_size);

因为std::string没有固定的大小(也可能为空),你必须确保分配了内存。在这里,我使用 std::stringresize() 函数来确保字符串中有足够的内存。填充字符串后,您必须手动调整字符串大小。

但是 recv 是一个普通的旧 C 函数,所以它不能自己调整大小 std::string

另一种解决方案是分配小字符数组并将其连接到包含全局响应的最终 std::string :

std::final final;

// retrieve small char array of max_size, for example equal to 256

final += std::string (buffer, max_size);

假设存储 space 是实际问题,链式缓冲区方法可能是一种解决方案。

#define MAX_BUF_LEN 10000
typedef struct netBuf
{
     char data[MAX_BUF_LEN];
     struct netBuf * pNext;
} NET_BUF;

NET_BUF * pHead = NULL;
NET_BUF *pCurrent = malloc(sizeof(NET_BUF));
pCurrent->pNext = NULL:
pHead = pCurrent;

char * pData = pCurrent->data;
int nDataLength;
int dataToRead = MAX_BUF_LEN;

while ((nDataLength = recv(Socket, pData, dataToRead, 0)) > 0) {
    if(dataToRead == nDataLength)
    {
        pCurrent->pNext = malloc(sizeof(NET_BUF));
        pCurrent = pCurrent->pNext;
        pCurrent->pNext = NULL;
        pData = pCurrent->data;
        dataToRead = MAX_BUF_LEN;
    }
    else
    {
        dataToRead -= nDataLength;
        pData +=nDataLength;
    }

}

好吧,让我们理性一点,摆脱那个可笑的巨大缓冲区。

char buffer[4096];
int nDataLength;
std::string result;
while ((nDataLength = recv(Socket, buffer, 4096, 0)) > 0) {
    std::copy_if(buffer, buffer + nDataLength, 
                 std::back_inserter(result),
                 [](char c) { 
                     return !std::isspace(c);
                     // maybe you wanted this instead?
                     // return std::isprint(c);
                 });
}
// result now contains your string, without any white space

在循环中将 string variablechar buffer 连接(连接在一起),如下所示:

 myString+=buffer[i];   // myString = myString + buffer[i];

示例代码清单:

#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <string>
#include <locale>
#pragma comment(lib,"ws2_32.lib")
using namespace std;

string myString;
locale local;


//***************************
void getWebsite(char *url );
//***************************


int main (){


    getWebsite("www.google.com" );
    for (size_t i=0; i<myString.length(); ++i) myString[i]= tolower(myString[i],local);

    cout <<myString;

    return 0;
}



//***************************
void getWebsite(char *url ){
    WSADATA wsaData;
    SOCKET Socket;
    SOCKADDR_IN SockAddr;


    int lineCount=0;
    int rowCount=0;

    struct hostent *host;
    char *getHttp= new char[256];

        memset(getHttp,' ', sizeof(getHttp) );
        strcpy(getHttp,"GET / HTTP/1.1\r\nHost: ");
        strcat(getHttp,url);
        strcat(getHttp,"\r\nConnection: close\r\n\r\n");

        if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0){
            cout << "WSAStartup failed.\n";
            system("pause");
            //return 1;
        }

         Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);


        host = gethostbyname(url);

        SockAddr.sin_port=htons(80);
        SockAddr.sin_family=AF_INET;
        SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);

        cout << "Connecting...\n";
            if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){
                cout << "Could not connect";
                system("pause");
                //return 1;
            }
        cout << "Connected.\n";

        //send(Socket,"GET / HTTP/1.1\r\nHost: www.cplusplus.com\r\nConnection: close\r\n\r\n", strlen("GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n"),0);

        send(Socket,getHttp, strlen(getHttp),0 );

        char buffer[10000];

        int nDataLength;
            while ((nDataLength = recv(Socket,buffer,10000,0)) > 0) {       
                int i = 0;

                while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {

                    myString+=buffer[i];  // myString = myString + buffer[i];
                    i += 1;
                }


            }
        closesocket(Socket);
        WSACleanup();

        delete[] getHttp;
}