2016-04-02 2 views
0

Я пишу консольное приложение с использованием 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; 
     } 
    } 

Мне нужно перевести буфер в строку перед тем, чтобы получить данные, потому что, если я использую массив символов буфер не большой, чтобы от чего прийти хранить entaire результат и если я увеличить размер, Visuale Студия показать мне ошибку при инициализации сокета

Я использую:

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); 

Это то, что мне нужно, чтобы сохранить ответ в строке, но: Как я могу это сделать?

ответ

1

Concatenate (объединяются) в string variable с char 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; 
} 

enter image description here

+0

вы получаете +1 от меня за то, что вы создали полный рабочий пример с ожидаемыми результатами; даже если вы совершили кардинальный грех, используя raw new/delete вместо интеллектуальных указателей ... По какой-то причине OP, похоже, хочет удалить пустое пространство из своих результатов. –

+0

@Software_Designer работает над вашим кодом, но если я вставляю путь, чтобы получить всю страницу, страница не приходит. Я говорю это: 'strcpy (getHttp," GET/cerca? Q = pasta HTTP/1.1 \ r \ nHost: ") ; ' –

0

Вы можете использовать это:

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 не имеет фиксированного размера (и, возможно, пустой), вы должны быть уверены, что память выделяется. Здесь я использую функцию resize()std::string, чтобы иметь достаточное количество памяти внутри строки. И после заполнения строки вы должны изменить размер строки вручную.

BUT recv - обычная старая функция C, поэтому она просто не может изменить размер std::string.

Другим решения является выделением небольшого массива символов и объединить его до конечного станда :: строки, которая содержит глобальный ответ:

std::final final; 

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

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

станд :: строка: : резервное резервное пространство, но не изменяет 'length()' строки. Первый ответ неверен. –

+0

@ RichardHodges исправлено – Garf365

+0

Это все еще не так. буфера построена по умолчанию. call reserve() на нем ничего не меняет. она по-прежнему равна нулю. адресация * (& buffer [0]) [что recv будет делать], поэтому неопределенное поведение. –

0

Предполагая, что пространство для хранения является фактически проблемой, A прикован буфер подхода может быть решение.

#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; 
    } 

} 
2

ОК, давайте будем разумными и избавимся от этого смехотворного огромного буфера.

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 
+0

, но для 'copy_if',' back_inserter' и 'isspace', какие библиотеки я должен включить? @RichardHodges –

Смежные вопросы