C++ Header

Hi, I've always used CURL, but I was forced to use sockets this time for some reason. This is my code;

#include "stdafx.h"
#include <winsock2.h>
#include <string>
#include <iostream>
using namespace std;

void HTTPReq(
    const char* verb,
    const char* hostname,
    int port,
    const char* resource,
    const char* opt_urlencoded,
    string& response)
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
    {
        cout << "WSAStartup failed.\n";
        exit(1);
    }

    SOCKET Socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    struct hostent *host;
    host = gethostbyname(hostname);

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

    if (connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0)
    {
        exit(1);
    }

    // Build request
    string req = verb; // GET | POST
    req.append(" ");
    // Note, on GET, 'resource' must contain the encoded parameters, if any:
    req.append(resource);
    req.append(" HTTP/1.1\r\n");

    req.append("Host: ");
    req.append(hostname);
    req.append(":");
    req.append(to_string(static_cast<long long>(port)));
    req.append("\r\n");

    if (strcmp(verb, "POST") == 0)
    {
        req.append("Cache-Control: no-cache\r\n");
        req.append("Content-length: ");
        req.append(to_string(static_cast<long long>(strlen(opt_urlencoded))));
        req.append("\r\n");
        req.append("Content-Type: application/x-www-form-urlencoded\r\n\r\n");

        // User is required to handle URI encoding for this value
        req.append(opt_urlencoded);

    }
    else // default, GET
    {
        req.append("Cache-Control: no-cache\r\n");
        req.append("Connection: close\r\n\r\n");
    }


    send(Socket, req.c_str(), req.size(), 0);

    char buffer[1024*10];
    int nlen;

    while ((nlen = recv(Socket,buffer,1024*10,0)) > 0)
    {
        response.append(buffer, 0, nlen);
    }
    closesocket(Socket);
    WSACleanup();

}

void main()
{
	string response;
    HTTPReq("GET", "MYIP", 80, "/crypto/index.php", NULL, response);

    cout << "==============================="
        << endl
        << response
        << endl
        << "=============================== "
        << endl;
}

Open in new window



My problem is that the code is returning beyond the response and header. I need only response! No need header...



a
magdiel linharesAsked:
Who is Participating?
 
sarabandeCommented:
you may try

int main()
{
    std::string response, result;
    HTTPReq("GET", "MYIP", 80, "/crypto/index.php", NULL, response);

    size_t lpos = response.find("Content-Type:");
    if (lpos != std::string::npos) 
    {
         lpos = response.find(std::endl, lpos+1);
         if (lpos  != std::string::npos)
         {
                result = response.substr(lpos+1);
                response.resize(lpos);
         }
    }
    
    std::cout << "==============================="
        << std::endl
        << response
        << std::endl
        << "=============================== "
        <<  result
        << std::endl;
        return 0;   // means no error
}

Open in new window


of course you should add some error handling (probably HTTPReq should return success or error code) and take advice from Fabrice.

Sara
0
 
Fabrice LambertFabrice LambertCommented:
Hi,

This is the way web servers answer to HTTP requests: with headers AND response (unless you ask for an HEAD request, in this case, you only get headers).
You'll have to parse the returned data and strip whatever you don't need.
But, don't overlook headers, they hold usefull data, starting with the error code returned by the server.
In you case: 200, wich mean the server processed your request without troubles (I suggest you take a look at HTTP error codes).

And while I'm at it:
Using the directive "using namespace std;" is considered a bad practice. It's sole purpose was to maintain hold code base when namespaces were introduced in C++ (back in 1990).
Modern codes should not use it.
Either fully qualify your functions call with the correct namespace or select precisely what you need:
int main()
{
    std::cout << "Hello world." << std::endl;
}

int main()
{
    using std::cout;
    using std::endl;

    cout << "Hello world." << endl;
}

Open in new window

Pre-declaring variables is also considered a bad practice, as it give vaiables a longer lifetime than needed.

The main function should return an integer, this inform the server that you app terminated as expected (return 0) or not.

Finally, concerning sockets, you might be interrested by the boost::asio library, wich is full C++ enabled (instead of using those horribles C-style arrays).
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.