Unable to receive HTTP response body C++ - c++

First, here is the C++ code I am using to make HTTP POST requests. It links to ws2_32.lib.
int POST_TEST(std::string URL, std::string DATA)
{
//**************************************************
std::string TEXT = "";
std::string DIRECTORY = URL.substr(URL.find(".com") + std::string(".com").length());
std::string HOST = URL.substr(0, URL.find(".com", std::string(".com").length())) + ".com";
std::string REQ = "POST " + DIRECTORY + " HTTP/1.1\r\nContent-Length: " + to_string(DATA.length()) + "\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nHost: " + HOST + "\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:44.0) Gecko/20100101 Firefox/44.0\r\nConnection: keep-alive\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n" + DATA;
const char * REQUEST = REQ.c_str();
//**************************************************
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return 1;
SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct hostent *host = gethostbyname(HOST.c_str());
SOCKADDR_IN SockAddr;
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)
return 1;
send(Socket, REQUEST, strlen(REQUEST), 0);
char buffer[1000];
int nDataLength;
while((nDataLength = recv(Socket, buffer, 1000, 0)) > 0)
{
int i = 0;
while(buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r')
{
TEXT += buffer[i];
i++;
}
}
closesocket(Socket);
WSACleanup();
MessageBoxA(NULL, TEXT.c_str(), "HTTP Response", MB_OK);
return 0;
}
POST_TEST("blah.com/a.php", "a=blah");
The code works well, but I am receiving only the HTTP Header response, and I don't see the response BODY. Making the POST request using Python to the same php page allows me to see the response body just fine. I'm not sure if I'm misunderstanding something, or there's an error in my code.
The PHP page I'm POSTing to is located on my own server. The PHP echoes some text, but I do not see that in the response. This is the response I get:
HTTP/1.1 200 OK
Server: nginx/1.8.1
Date: Fri, 08 Apr 2016 02:10:14 GMT
Content-Type: text/html
Content-Length: 286
Connection: keep-alive
Vary: Accept-Encoding
Content-Encoding: gzip
How would I be able to see the entire response?

There are two bugs in the shown code.
It doesn't check the return value from send(). send() does not guarantee that the number of bytes requested to be sent was actually sent. The return value from send() may return an indication that fewer bytes were written than what were requested. It is your responsibility to check that, and try again to send() the remaining bytes.
The logic for reading and collecting the response is wrong. recv() tells you how many bytes were received. This is ignored completely. Instead, the code scans the read buffer until it sees a control character as a byte.
Note that your HTTP response indicates that you're getting raw, gzip-compressed binary data. It is fairly likely that within the first few bytes of the actual response there are going to be some binary bytes that correspond to ASCII control characters, in value. Your loop will come to a screeching halt at that point.
Even if you were expecting a plain text response, this logic would still be wrong. It is the return value from recv() that tells you how many bytes were received, and nothing else.

Related

C Raw Sockets HTTP Request Always Returning Status 400

I normally write a bunch of Typescript/Javascript code, and I took the HTTP protocol for granted. I decided to write a C++ program that can make GET requests to a given URL with sockets to learn more about how HTTP works. I've coded up what I think is the basic structure of what I should be doing:
Create a socket
Connect the socket to host
Send request byte by byte
Received response byte by byte
The issue is that the request always returns status code 400:
>>>> Request sent:
GET /links HTTP/1.1
>>>> Response received:
HTTP/1.1 400 Bad Request
Server: cloudflare
Date: Sun, 11 Oct 2020 05:57:11 GMT
Content-Type: text/html
Content-Length: 155
Connection: close
CF-RAY: -
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>cloudflare</center>
</body>
</html>
Here's the code I'm using to create the socket and connect it to the host:
// ---- Create the socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("!!!! ERROR opening socket");
// ---- Look up (and parse) the server host, route
std::string host = parseHost(url);
std::string route = parseRoute(url);
struct hostent *server = gethostbyname(host.c_str()); // host.c_str())
if (server == NULL)
error("!!!! ERROR, no such host");
// ---- Fill in the server address structure
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT); // PORT
memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length);
// ---- Connect the socket to the given url's host
const int didConnect = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (didConnect < 0) error("!!!! ERROR connecting to host");
If that logic seems correct, then here's the code that sends the request and receives the response:
// ---- Send the GET request byte by byte
int bytes, sent, received;
char response[MAX_CONTENT_LENGTH];
int total = sizeof(response) - 1;
sent = 0;
std::string message = "GET " + route + "HTTP/1.1" + "\r\n\r\n";
do
{
bytes = write(sockfd, message.c_str() + sent, total - sent);
if (bytes < 0) error("!!!! ERROR writing message to socket");
if (bytes == 0) break;
sent += bytes;
} while (sent < total);
std::cout << ">>>> Request sent: \n" << message << std::endl;
// ---- Receive the response byte by byte
memset(response, 0, sizeof(response));
total = sizeof(response) - 1;
received = 0;
do {
bytes = read(sockfd, response + received, total - received);
if (bytes < 0)
error("!!!! ERROR reading response from socket");
if (bytes == 0)
break;
received += bytes;
} while (received < total);
if (received == total)
error("!!!! ERROR storing complete response from socket (not enough space allocated)");
TLDR: Am I sending the right char array to the server? As of right now it has this format: "GET /route HTTP/1.1\r\n\r\n". Am I forgetting any headers/other information that lets the server know that it's a GET request?
>>>> Request sent:
GET /links HTTP/1.1
This is not a valid HTTP request. It is missing the Host header with the target domain name, i.e. it should be at least something like this
GET /links HTTP/1.1
Host: www.example.com
Apart from that your code simply tries to read data until the server closes the connection or the size of your internal buffer is reached. But HTTP/1.1 by default uses persistent connection. So the server might simply keep the connection open after the response is sent because it expects your next request, which means that your program will simply block doing nothing.
Note that HTTP is far more complex than it looks. Please study the actual standard if you want to implement it instead of using existing libraries. That's what standards are for.

Receive (recv) full request (e.g. curl HTTP)

How should this be done?
I want to receive a (rather long) HTTP request and cannot get this to work.
The problem: Without flags, recv does not read the whole message. I guess this is normal behavior. From what I understand using the MSG_WAITALL flag causes it to block until everything is received. However, in that case the call blocks forever (until I ctrl+c the client (curl) process.
Below there is a (still lengthy, but rather minimal) example snippet.
Sorry it mixes C and C++ style but I wanted to avoid own errors and sticked largely to example code with as few modifications as possible.
// Example largely based on: beej.us/guide/bgnet/output/html/singlepage/bgnet.html
// Mixes c-style and c++ due to my modifications.
// Only intended to reproduce a problem.
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sstream>
#include <iostream>
#include <cstring>
#define PORT "7004" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void)
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(servinfo); // all done with this structure
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
printf("server: waiting for connections...\n");
while(1) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
const uint EASILY_ENOUGH = 1000000;
char* buffer = new char[EASILY_ENOUGH + 1];
auto bytesRead = recv(new_fd, buffer, EASILY_ENOUGH, MSG_WAITALL); // FREEZES UNTIL I KILL THE CLIENT
// auto bytesRead = recv(new_fd, buffer, EASILY_ENOUGH, 0); // DOES NOT READ FULL REQUEST
if (bytesRead == -1) {
perror("recv");
close(new_fd);
continue;
}
buffer[bytesRead] = 0;
printf("bytes read: %ld\n", bytesRead);
printf("request: %s\n", buffer);
delete[] buffer;
std::string content = "some content.";
std::ostringstream os;
os << "HTTP/1.1 200 OK\r\n" << "Content-Length: " << content.size() << "\r\n"
<< "Connection: close\r\n" << "Content-Type: " << "plain/text"
<< "; charset=" << "utf-8" << "\r\n"
<< "Access-Control-Allow-Origin: *" << "\r\n" << "\r\n" << content;
std::string response = os.str();
printf("Response has size: %ld\n", response.size());
auto bytesSent = send(new_fd, response.c_str(), response.size(), 0);
printf("Method send claims it has sent %ld bytes\n", bytesSent);
close(new_fd);
}
return 0;
}
The curl resquest i used:
curl 'http://<myhost>:7004/___THE START___jsondsadasdasdzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwaghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewjfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwasondsadasdasdzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwaghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewjfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwasondsadasdasdzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwaghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewjfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwasondsadasdasdzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwaghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewjfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwa___THE END'
With MSG_WAITALL my server produces the output:
server: waiting for connections...
server: got connection from <my ip>
and hangs, once I CTRL+C curl it progresses with:
bytes read: 6379
request: GET /___THE START___jsondsadasdasdzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwaghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewjfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwasondsadasdasdzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwaghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewjfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwasondsadasdasdzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwaghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewjfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwasondsadasdasdzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwaghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewjfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwa___THE END HTTP/1.1
Host: <myhost>:7004
User-Agent: curl/7.49.0
Accept: */*
Response has size: 144
Method send claims it has sent 144 bytes
Without MSG_WAITALL and the same request, the server produces the output:
server: waiting for connections...
server: got connection from <my ip>
bytes read: 1448
request: GET /___THE START___jsondsadasdasdzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwaghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewjfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiwehfoewhfiuewhfiewhfhfiuewhfiwehfiuewwehgurwadzughjdssftzghuijerdftzghujiesdhufdewojfoewfhoiw
Response has size: 144
Method send claims it has sent 144 bytes
And curl does not receive the HTTP response.
However, a shorter request properly receives the response:
curl 'http://myhost:7004/___THE START___THE END__'
> some content.
And the server properly received the full request:
server: got connection from <my ip>
bytes read: 128
request: GET /___THE START___THE END__ HTTP/1.1
Host: <myhost>:7004
User-Agent: curl/7.49.0
Accept: */*
Response has size: 144
Method send claims it has sent 144 bytes
I do understand that it is normal that not all TCP packets arrive right away. However, what is the correct way for me to assemble the full request? I also tried non-blocking variants but usually ran into situations where no more data was ready for reading. If necessary I can produce sample code for this, similarly.
PS: The problem manifests when request length and connection badness exceed a threshold. I cannot reproduce it on my own machine with queries to localhost, and depending on my connection, the request length where problems start to manifest varies.
HTTP is a protocol, it has structure and rules to it. Read RFC 2616, particularly Section 4 "HTTP Message".
Your recv code is not doing anything to follow the protocol at all. You can't just blindly read an arbitrary buffer of data and expect it to be the complete HTTP request correctly. You have to read the request according to the rules of the protocol. Specifically, you need to:
read a CRLF delimited line of text. This will contain the requested method, resource, and HTTP version.
then read a variable length list of CRLF delimited request headers. The list is terminated by a CRLF CRLF sequence.
then analyze the request method and headers to determine whether the request has an entity body. If so, the headers will tell you how it is encoded over the connection (see Section 4.4 "Message Length"), so you know how it needs to be read and when you need to stop reading.
then process the completed request, and send your response.
then close the connection, unless either:
the request asked for HTTP 1.0 and Connection: keep-alive is present in the request headers.
the request asked for HTTP 1.1+ and Connection: close is not present in the request headers.

Forwarding traffic to another device using C++

I am trialling a little project for Philips Hue and learning c++ at the same time. What I am trying to do is act a proxy between a client and the bridge. The app runs as a bridge as far as any clients are concerned, receives the request and passes this on to the bridge.
I have a weird problem where if the app runs normally, I only get a HTTP 200 OK response, nothing else, if I step through the code, I get the full response.
Below is my code, there is no thread, there are no classes, its all being done in the main method.
WindowsSocket socketManager(&bitsLibrary);
if (!socketManager.createSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 80, 1024))
{
cout << "Failed to create socket" << endl;
}
socketManager.bindAndStartListening();
WindowsSocket bridgeSocketManager(&bitsLibrary);
while (true)
{
sockaddr_in clientAddr;
memset(&clientAddr, 0, sizeof(sockaddr_in));
SOCKET clientSocket = socketManager.acceptClientAndReturnSocket(&clientAddr);
this_thread::sleep_for(chrono::milliseconds(500));
string received = socketManager.receiveDataOnSocket(&clientSocket);
bitsLibrary.writeToLog(received);
struct sockaddr_in server;
server.sin_family = AF_INET;
//server.sin_addr.s_addr = inet_addr("139.162.223.149");
server.sin_addr.s_addr = inet_addr("192.168.1.67");
server.sin_port = htons(80);
bridgeSocketManager.createSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
this_thread::sleep_for(chrono::milliseconds(500));
int result = connect(*bridgeSocketManager.returnSocket(), (struct sockaddr *)&server, sizeof(server));
if (result < 0)
{
cout << "Connect Failed: " << WSAGetLastError() << endl;
return EXIT_FAILURE;
}
this_thread::sleep_for(chrono::milliseconds(500));
SOCKET * bridgeSocket = bridgeSocketManager.returnSocket();
this_thread::sleep_for(chrono::milliseconds(500));
socketManager.sendToSocket(bridgeSocket, received);
string reply = socketManager.receiveDataOnSocket(bridgeSocket);
//boost::replace_all(reply, "Host: 192.168.1.70", "Host: 192.168.1.67");
bitsLibrary.writeToLog(reply);
this_thread::sleep_for(chrono::milliseconds(1000));
int sent = socketManager.sendToSocket(&clientSocket, reply);
this_thread::sleep_for(chrono::milliseconds(500));
bridgeSocketManager.closeSocket();
this_thread::sleep_for(chrono::milliseconds(500));
socketManager.closeSocket(&clientSocket);
/*while (true)
{
SOCKET clientSocket = socketManager.acceptClientAndReturnSocket(&clientAddr);
SocketProcessor socketProcessor;
socketProcessor.startThread(socketManager, clientSocket);
}*/
}
socketManager.closeSocket();
My socket receive method is as follows:
std::string WindowsSocket::receiveDataOnSocket(SOCKET *socket)
{
if (*socket != -1)
{
string receivedData = "";
char *temp = NULL;
int bytesReceived = 0;
do
{
bytesReceived = recv(*socket, this->buffer, this->bufferLength, 0);
if (bytesReceived == SOCKET_ERROR)
{
string socketError = this->getErrorStringFromErrorCode(WSAGetLastError()).c_str();
stringstream logstream;
logstream << "Failed to receive data on socket.The socket will now be closed and cleanup performed. Error: " << socketError;
this->bitsLibrary->writeToLog(logstream.str(), "WindowsSocket", "receiveDataOnSocket");
closesocket(*socket);
WSACleanup();
throw SocketException(socketError.c_str());
return "";
}
//If we got here, then we should be able to get some data
temp = new char[bytesReceived + 1];
//memset(&temp, 0, bytesReceived + 1);
strncpy(temp, this->buffer, bytesReceived);
temp[bytesReceived] = '\0'; //Add a null terminator to the end of the string
receivedData.append(temp);
temp = NULL;
//Now clear the buffer ready for more data
memset(this->buffer, 0, this->bufferLength);
cout << "Bytes Received: " << bytesReceived << " BUffer Length: " << this->bufferLength << endl;
} while (bytesReceived == this->bufferLength && bytesReceived >= 0); //Keep going until the received bytes is less than the buffer length
return receivedData;
}
else
{
stringstream logstream;
logstream << "Can't receive on socket as already be closed";
throw SocketException(logstream.str().c_str());
}
}
The send method looks as follows:
int WindowsSocket::sendToSocket(SOCKET *clientSocket, string dataToSend)
{
//dataToSend.append("\r\n");
int sentBytes = send(*clientSocket, dataToSend.c_str(), dataToSend.length(), 0);
if (sentBytes == SOCKET_ERROR)
{
throw SocketException(this->getErrorStringFromErrorCode(WSAGetLastError()).c_str());
}
return sentBytes;
}
When I run the app normally in Visual Studio with no break points, I get the following output:
03/02/2017 22:08:16: WindowsSocket/bindAndStartListening: Socket has binded and is now listening
Bytes Received: 413 BUffer Length: 1024
Receiving data
GET /api/nouser/config HTTP/1.1
Host: 192.168.1.70
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en;q=0.8
03/02/2017 22:08:22: BaseSocket/createSocket: Creating buffer of length 1024
Bytes Received: 17 BUffer Length: 1024
03/02/2017 22:08:23: HTTP/1.1 200 OK
Sent: 17
If I set a breakpoint and then step through the code I get the following:
03/02/2017 22:09:03: WindowsSocket/bindAndStartListening: Socket has binded and is now listening
Bytes Received: 413 BUffer Length: 1024
GET /api/nouser/config HTTP/1.1
Host: 192.168.1.70
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en;q=0.8
03/02/2017 22:09:09: BaseSocket/createSocket: Creating buffer of length 1024
Bytes Received: 630 BUffer Length: 1024
03/02/2017 22:09:17: HTTP/1.1 200 OK
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Expires: Mon, 1 Aug 2011 09:00:00 GMT
Connection: close
Access-Control-Max-Age: 3600
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE, HEAD
Access-Control-Allow-Headers: Content-Type
Content-type: application/json
{"name":"Philips hue","datastoreversion":"59","swversion":"01036659","apiversion":"1.16.0","mac":"00:17:88:1a:1f:43","bridgeid":"001788FFFE1A1F43","factorynew":false,"replacesbridgeid":null,"modelid":"BSB001"}
Sent: 630
Notice when I don't do a break point I receive only 17 bytes of the HTTP 200 OK but when I breakpoint and step through the code I then get over 600 bytes and receive everything that I was expecting.
I can't see what the problem is, I've put sleeps in expecting this would "fix" the issue but even the sleeps make no difference.
send()/recv() are low-level calls to work with sockets. To properly handle HTTP, which is quite a complex protocol, you should be aware of HTTP specification, see about-to-become-obsolete RFC2616.
Your best bet is to set condition in do-while loop of receiveDataOnSocket() to while (bytesReceived > 0). It will only work, if server closes connection after sending the response.
If persistent connection is used, then the next best thing you can do is to use non-blocking sockets (at least for accepting data from both client and server) and as data arrives, forward them to other side. It may work, but may also fail.
The next thing is actually implementing HTTP, which is too complex for C++ tutorial.

How to send POST Request and receive GET response

I'm trying to send a POST Request and receive a GET response in return.
Here is my code :
#define IP "87.98.245.77"
#define Port 80
void getGETMessage(SOCKET s)
{
char *data = new char[2000];
recv(s, data, strlen(data), NULL);
int x = 3;
}
void SendPOSTMessage(SOCKET s)
{
string data = "POST /index.php?p=convert HTTP/1.1"
"Host: convert2mp3.netConnection: keep-alive"
"Content-Length: 80";
"Cache-Control: max-age=0"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
"Origin: http://convert2mp3.net"
"User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36"
"Content-Type: application/x-www-form-urlencoded"
"Referer: http://convert2mp3.net/index.php?p=home"
"Accept-Encoding: gzip,deflate,sdch"
"Accept-Language: he-IL,he;q=0.8,en-US;q=0.6,en;q=0.4,de;q=0.2,fr;q=0.2";
if (send(s, data.c_str(), data.length(), NULL) < data.length())
{
cout << "Error : " << WSAGetLastError() << endl;
return ;
}
getGETMessage(s);
}
int main()
{
char *data = new char[200];
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(IP); // IP
clientService.sin_port = htons(Port); // Port
iResult = connect(ConnectSocket, (SOCKADDR *)& clientService, sizeof(clientService));
if (iResult == SOCKET_ERROR)
{
cout << "Error" << endl;
return 0;
}
SendPOSTMessage(ConnectSocket);
cin.get();
cin.get();
}
For some reason, I'm not getting anything back...
I tried getting the IP of this website :
http://convert2mp3.net/index.php?p=home and using cmd, it told me it's http://87.98.245.77/ but it doesn't load in my browser... Maybe this is my error?
Thanks!
Your data is invalid. Each HTTP header needs to be terminated by \r\n, and you need another one after the last line of headers. And you're sending a Content-length of 80 but no content.
Further notes:
If send() returns a positive integer, calling WSAGetLastError() is meaningless. There has been no error, so what you will get is undefined. You should check for -1. In practice send() won't return a short count unless you're in non-blocking mode.
NULL is not a correct fourth parameter for send() or recv(), but 0 is.
There is no such thing as a 'GET response'. There are just HTTP responses.
Problem (at least one) is in this part of code:
void getGETMessage(SOCKET s)
{
char *data = new char[2000];
recv(s, data, strlen(data), NULL);
int x = 3;
}
You didn't initialized data, so, there may be any symbols, so strlen(data) may return 0, if first symbol will be '\0', or something else, depends on when '\0' will appears.
Try to change strlen to sizeof.
Something like that:
void getGETMessage(SOCKET s)
{
char data[2000] = {0};
recv(s, data, sizeof(data)-1, NULL);
cout << data << endl;
int x = 3;
}
Based on your code, you're only sending the header information. You specify a Content-Length of 80, but you're not sending any data. Therefore, the server is still waiting on the data and is not sending a response back to you yet.
My suggestion would be to utilize some HTTP library rather than attempt to perform all the low-level functionality yourself. Some suggestions are in this Stack Overflow question.

Simple Http Get Response

I have been writing a simple web server (http 1.0) for a class, but whenever I try to get a file (wget 127.0.0.1 /filename) is is short a few bytes. The confusing thing is when I sum the number of sent bytes it matches the file size, but not the amount wget receives.
Why is wget not getting all of the data I write to the socket?
some wget output
wget:
--2012-10-27 19:02:00-- (try: 4) http://127.0.0.1:5555/
Connecting to 127.0.0.1:5555... connected.
HTTP request sent, awaiting response... 200 Document follows
Length: 5777 (5.6K) [text/html]
Saving to: `index.html.6'
99% [=====================================> ] 5,776 --.-K/s in 0s
2012-10-27 19:02:00 (322 MB/s) - Read error at byte 5776/5777 (Connection reset by peer). Retrying.
--2012-10-27 19:03:52-- (try: 4) http://127.0.0.1:5555/ZoEY8.jpg
Connecting to 127.0.0.1:5555... connected.
HTTP request sent, awaiting response... 200 Document follows
Length: 163972 (160K) [image/jpeg]
Saving to: `ZoEY8.jpg.4'
91% [==================================> ] 149,449 --.-K/s in 0.001s
2012-10-27 19:03:52 (98.8 MB/s) - Read error at byte 163917/163972 (Connection reset by peer). Retrying.
Get method:
void *
processGetRequest(requestParser request)
{
string resp= "HTTP/1.0 200 Document follows\r\nServer: lab5 \r\nContent-Length: ";
string path="";
path =request.path;
//find file
int page= open (path.c_str(),O_RDONLY);
FILE * pageF= fdopen(page,"rb");
//get size
fseek(pageF, 0L, SEEK_END);
int sz = ftell(pageF);
fseek(pageF, 0L, SEEK_SET);
//form content length
stringstream ss;
ss<<resp<<sz<<"\r\n";
resp=ss.str();
//make response
if(page<0){
cout<<"404 \n";
resp = "HTTP/1.0 404 File Not Found\r\nServer: lab5 \r\nContent-type: text/html \r\n \r\n";
write( request.fd, resp.c_str(), resp.length());
return 0;
}
if(path.find(".gif")!=string::npos)
resp += "Content-type: image/gif\r\n \r\n";
else if(path.find(".png")!=string::npos)
resp += "Content-type: image/png\r\n \r\n";
else if(path.find(".jpg")!=string::npos)
resp += "Content-type: image/jpeg\r\n \r\n";
else
resp += "Content-type: text/html \r\n \r\n";
//write response
write( request.fd, resp.c_str(), resp.length());
int total=0;
char buff[1024];
int readBytes = 0;
int er;
//send file
do{
readBytes= read(page, buff, 1024);
cout<<"read bytes "<<readBytes<<"\n";
if(readBytes<0){
perror("read");
break;
}
total+=readBytes;
er= send( request.fd, buff, readBytes,0 );
cout<<"sent bytes "<<er<<"\n";
if (er==-1){
perror("send");
}
else if( er != readBytes){
cout<<"Read write miss match\n";
}
}while(readBytes>0);
close(page);
return 0;
}
Edit:
I have been working at this while and I'm wondering if Im doing my sockets wrong
// Set the IP address and port for this server
struct sockaddr_in serverIPAddress;
memset( &serverIPAddress, 0, sizeof(serverIPAddress) );
serverIPAddress.sin_family = AF_INET;
serverIPAddress.sin_addr.s_addr = INADDR_ANY;
serverIPAddress.sin_port = htons((u_short) port);
// Allocate a socket
int masterSocket = socket(PF_INET, SOCK_STREAM, 0);
if ( masterSocket < 0) {
perror("socket");
exit( -1 );
}
while ( 1 ) {
// Accept incoming connections
struct sockaddr_in clientIPAddress;
int alen = sizeof( clientIPAddress );
int slaveSocket = accept( masterSocket,
(struct sockaddr *)&clientIPAddress,
(socklen_t*)&alen);
// send slaveSocket to get method
}
My first answer is below, but i just noticed something..
"Content-type: text/html \r\n \r\n";
The headers must be separated from the content with two CR/LF. It looks like you have space in there
you can try this:
"Content-type: text/html\r\n\r\n";
Is the output buffer being correctly flushed and closed after the last write? Try changing the size of your 1024 byte read buffer to something larger than your gif file. This isnt a fix, but you may get different results, and this may help track down the cause of the problem. Maybe also put some logging into the read write loop. See if the size of the last buffer write equals the number of bytes the response is missing.