Считать значение файла и записать его в переменную по URL C++

Ознакомилась с различными методами в вопросах 1, 2 и 3, но хотелось бы метод на чистом С++ без сторонних библиотек. Из всех вышеперечисленных методов я извлекла три на чистом С++, но в двух из них возникают ошибки на этапе компиляции, а в 1 возникает ошибка в коде. Ниже я вставлю код этих методов и какие в них возникают ошибки.

Первый метод:

#include <windows.h>
#include <string>
#include <stdio.h>

using std::string;

#pragma comment(lib,"ws2_32.lib")


HINSTANCE hInst;
WSADATA wsaData;
void mParseUrl(char* mUrl, string& serverName, string& filepath, string& filename);
SOCKET connectToServer(char* szServerName, WORD portNum);
int getHeaderLength(char* content);
char* readUrl2(char* szUrl, long& bytesReturnedOut, char** headerOut);


int main()
{
    const int bufLen = 1024;
    char* szUrl = "http://stackoverflow.com";
    long fileSize;
    char* memBuffer, * headerBuffer;
    FILE* fp;

    memBuffer = headerBuffer = NULL;

    if (WSAStartup(0x101, &wsaData) != 0)
        return -1;


    memBuffer = readUrl2(szUrl, fileSize, &headerBuffer);
    printf("returned from readUrl\n");
    printf("data returned:\n%s", memBuffer);
    if (fileSize != 0)
    {
        printf("Got some data\n");
        fp = fopen("downloaded.file", "wb");
        fwrite(memBuffer, 1, fileSize, fp);
        fclose(fp);
        delete(memBuffer);
        delete(headerBuffer);
    }

    WSACleanup();
    return 0;
}


void mParseUrl(char* mUrl, string& serverName, string& filepath, string& filename)
{
    string::size_type n;
    string url = mUrl;

    if (url.substr(0, 7) == "http://")
        url.erase(0, 7);

    if (url.substr(0, 8) == "https://")
        url.erase(0, 8);

    n = url.find('/');
    if (n != string::npos)
    {
        serverName = url.substr(0, n);
        filepath = url.substr(n);
        n = filepath.rfind('/');
        filename = filepath.substr(n + 1);
    }

    else
    {
        serverName = url;
        filepath = "/";
        filename = "";
    }
}

SOCKET connectToServer(char* szServerName, WORD portNum)
{
    struct hostent* hp;
    unsigned int addr;
    struct sockaddr_in server;
    SOCKET conn;

    conn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (conn == INVALID_SOCKET)
        return NULL;

    if (inet_addr(szServerName) == INADDR_NONE)
    {
        hp = gethostbyname(szServerName);
    }
    else
    {
        addr = inet_addr(szServerName);
        hp = gethostbyaddr((char*)&addr, sizeof(addr), AF_INET);
    }

    if (hp == NULL)
    {
        closesocket(conn);
        return NULL;
    }

    server.sin_addr.s_addr = *((unsigned long*)hp->h_addr);
    server.sin_family = AF_INET;
    server.sin_port = htons(portNum);
    if (connect(conn, (struct sockaddr*)&server, sizeof(server)))
    {
        closesocket(conn);
        return NULL;
    }
    return conn;
}

int getHeaderLength(char* content)
{
    const char* srchStr1 = "\r\n\r\n", * srchStr2 = "\n\r\n\r";
    char* findPos;
    int ofset = -1;

    findPos = strstr(content, srchStr1);
    if (findPos != NULL)
    {
        ofset = findPos - content;
        ofset += strlen(srchStr1);
    }

    else
    {
        findPos = strstr(content, srchStr2);
        if (findPos != NULL)
        {
            ofset = findPos - content;
            ofset += strlen(srchStr2);
        }
    }
    return ofset;
}

char* readUrl2(char* szUrl, long& bytesReturnedOut, char** headerOut)
{
    const int bufSize = 512;
    char readBuffer[bufSize], sendBuffer[bufSize], tmpBuffer[bufSize];
    char* tmpResult = NULL, * result;
    SOCKET conn;
    string server, filepath, filename;
    long totalBytesRead, thisReadSize, headerLen;

    mParseUrl(szUrl, server, filepath, filename);

    ///////////// step 1, connect //////////////////////
    conn = connectToServer((char*)server.c_str(), 80);

    ///////////// step 2, send GET request /////////////
    sprintf(tmpBuffer, "GET %s HTTP/1.0", filepath.c_str());
    strcpy(sendBuffer, tmpBuffer);
    strcat(sendBuffer, "\r\n");
    sprintf(tmpBuffer, "Host: %s", server.c_str());
    strcat(sendBuffer, tmpBuffer);
    strcat(sendBuffer, "\r\n");
    strcat(sendBuffer, "\r\n");
    send(conn, sendBuffer, strlen(sendBuffer), 0);

    //    SetWindowText(edit3Hwnd, sendBuffer);
    printf("Buffer being sent:\n%s", sendBuffer);

    ///////////// step 3 - get received bytes ////////////////
    // Receive until the peer closes the connection
    totalBytesRead = 0;
    while (1)
    {
        memset(readBuffer, 0, bufSize);
        thisReadSize = recv(conn, readBuffer, bufSize, 0);

        if (thisReadSize <= 0)
            break;

        tmpResult = (char*)realloc(tmpResult, thisReadSize + totalBytesRead);

        memcpy(tmpResult + totalBytesRead, readBuffer, thisReadSize);
        totalBytesRead += thisReadSize;
    }

    headerLen = getHeaderLength(tmpResult);
    long contenLen = totalBytesRead - headerLen;
    result = new char[contenLen + 1];
    memcpy(result, tmpResult + headerLen, contenLen);
    result[contenLen] = 0x0;
    char* myTmp;

    myTmp = new char[headerLen + 1];
    strncpy(myTmp, tmpResult, headerLen);
    myTmp[headerLen] = NULL;
    delete(tmpResult);
    *headerOut = myTmp;

    bytesReturnedOut = contenLen;
    closesocket(conn);
    return(result);
}

В нём возникает ошибка на строке 21: значение типа const char* нельзя присвоить сущности типа char *

Второй метод:

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




int main(void) {

    WSADATA wsaData;
    SOCKET Socket;
    SOCKADDR_IN SockAddr;
    int lineCount = 0;
    int rowCount = 0;
    struct hostent* host;
    locale local;
    char buffer[10000];
    int i = 0;
    int nDataLength;
    string website_HTML;

    // website url
    string url = "www.google.com";

    //HTTP GET
    string get_http = "GET / HTTP/1.1\r\nHost: " + url + "\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.c_str());

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

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

    // send GET / HTTP
    send(Socket, get_http.c_str(), strlen(get_http.c_str()), 0);

    // recieve html
    while ((nDataLength = recv(Socket, buffer, 10000, 0)) > 0) {
        int i = 0;
        while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {

            website_HTML += buffer[i];
            i += 1;
        }
    }

    closesocket(Socket);
    WSACleanup();

    // Display HTML source 
    cout << website_HTML;

    // pause
    cout << "\n\nPress ANY key to close.\n\n";
    cin.ignore(); cin.get();


    return 0;
}

В нём возникают ошибки на этапе компиляции: строка 42: error C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings #define _WINSOCK_DEPRECATED_NO_WARNINGS не решает проблему.

И третий метод:

#include <winsock2.h>
#include <windows.h>
#include <string>
#include <iostream>
#include <cstring>
#pragma comment(lib, "ws2_32.lib")

char* parse_url(char* d, const char* url);
int   ReadUrl(const char* url, std::string& dst, DWORD msec = WSA_INFINITE);


int main(void){
    WSADATA wd = {0};
    if(WSAStartup(MAKEWORD(2, 2), &wd) != 0)
         return EXIT_FAILURE;

    std::string buf;

    char url[] = "http://mysite.ru/version.txt";
    int    err = ::ReadUrl(url, buf, 12000);
    if(err == ERROR_SUCCESS)
         std::cout << buf;
    else
         std::cerr << "error, code: " << err;

    std::cout << std::endl;

    WSACleanup();
    std::cin.get();
    return 0;
}


int ReadUrl(const char* url, std::string& dst, DWORD msec){
    int      ret;
    char     host[64];
    SOCKET   sock;
    WSAEVENT hevent;

    if(! *parse_url(host, url))
        return WSAEFAULT;

    hevent = WSACreateEvent();
    if(hevent == WSA_INVALID_EVENT)
        return WSAGetLastError();

    // создаём сокет
    sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 
                     NULL, 0, WSA_FLAG_OVERLAPPED);
    if(sock == INVALID_SOCKET){
        ret = WSAGetLastError();
        WSACloseEvent(hevent);
        return ret;
    }

    //получаем IP
    hostent* phost = gethostbyname(host);
    if(phost == NULL){
        ret = WSAGetLastError();
        WSACloseEvent(hevent);
        closesocket(sock);
        return ret;
    }

    sockaddr_in addr = {0};
    addr.sin_family  = AF_INET;
    addr.sin_port    = htons(80);
    CopyMemory(&addr.sin_addr, phost->h_addr_list[0], phost->h_length);

    // коннектимся к хосту
    ret = connect(sock, (const sockaddr*)&addr, sizeof(addr)); 
    if(ret == SOCKET_ERROR) {
        ret = WSAGetLastError();
        WSACloseEvent(hevent);
        closesocket(sock);
        return ret;
    }

    // задаём запрос
    dst  = "GET ";
    dst += url;
    dst += "\r\n\r\n";

    ret  = send(sock, &dst[0], dst.length(), 0);
    dst  = "";

    Sleep(50);
    if(ret == SOCKET_ERROR) {
        ret = WSAGetLastError();
        WSACloseEvent(hevent);
        closesocket(sock);
        return ret;
    }

    //***

    WSAOVERLAPPED wso;
    WSABUF wbuf;
    DWORD  len, flag;
    char   buf[512];

    wbuf.buf = &buf[0];
    wbuf.len = sizeof(buf) - 1;

    //чтение
    while(1){
        ZeroMemory(&wso, sizeof(wso));
        wso.hEvent  = hevent;
        len  = flag = 0;

        ret  = WSARecv(sock, &wbuf, 1, &len, &flag, &wso, NULL);
        if(ret == SOCKET_ERROR){
            if((ret = WSAGetLastError()) != WSA_IO_PENDING)
                 break;
        }

        ret = WSAWaitForMultipleEvents(1, &hevent, FALSE, msec, FALSE);
        if((ret == WSA_WAIT_FAILED) || (ret == WSA_WAIT_TIMEOUT)){
            ret = (! dst.length()) ? SOCKET_ERROR : 0;
            break;
        }
        WSAResetEvent(hevent);

        ret -= WSA_WAIT_EVENT_0;
        if(ret < 0 || ret > 0){
            ret = (! dst.length()) ? SOCKET_ERROR : 0;
            break;          
        }

        len = 0;
        ret = WSAGetOverlappedResult(sock, &wso, &len, FALSE, &flag);
        if((! len) || (! ret)){
            if((ret = WSAGetLastError()) != WSA_IO_INCOMPLETE)
                 break;
            continue;
        }

        if(len > 0){
            buf[len] = '\0';
            dst.append(buf, buf + len); 
        }
   }

   WSASetEvent(hevent);
   WSACloseEvent(hevent);
   closesocket(sock);
   return (ret == SOCKET_ERROR) ? WSAGetLastError() : ERROR_SUCCESS;
}


char* parse_url(char* d, const char* url){
    char* t = d;
    if(! strnicmp(url, "http://", 7))
        url += 7;

    while(*url && (*url != '/'))
        *d++ = *url++;
   *d = '\0';
   return t;
}

В нём возникают ошибки на этапе компиляции: строка 57: та же ошибка, что и в предыдущем: error C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings. Также возникает ошибка на строке 153: error C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _strnicmp. See online help for details., но она легко решается заменой strnicmp на _strnicmp.

Так вот, хотелось бы узнать, какой метод лучше использовать для считывания значения с файла на сервере и как исправить ошибки? Хотя возможно есть и другой(-е) метод(-ы), которые лучше подойдут для этой задачи...


Ответы (0 шт):