Recv() Function Hangs After Sending HTTP GET Request in Winsock in C++ - c++

I am trying to make a program that uses HTTP in winsock, but I have run into a problem where the recv function just hangs there.
int connect()
{
WSADATA t_wsa; //WSADATA structure
WORD wVers = 0x0202; //version number
int iError; //error number
wVers = MAKEWORD(2, 2); // Set the version number to 2.2
iError = WSAStartup(wVers, &t_wsa); // Start the WSADATA
if(iError != NO_ERROR || iError == 1)
{
printf("Error at WSAStartup()\n");
WSACleanup();
system("PAUSE");
return 1;
}
/* Correct version? */
if(LOBYTE(t_wsa.wVersion) != 2 || HIBYTE(t_wsa.wVersion) != 2)
{
printf("Incorrect version\n");
WSACleanup();
system("PAUSE");
return 1;
}
SOCKET sClient;
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sClient == INVALID_SOCKET || iError == 1)
{
printf("Invalid Socket!\n");
WSACleanup();
system("PAUSE");
return 1;
}
SOCKADDR_IN sinClient;
memset(&sinClient, 0, sizeof(sinClient));
char cIP[50];
strcpy_s(cIP, "98.139.183.24");
sinClient.sin_family = AF_INET;
sinClient.sin_addr.s_addr = inet_addr(cIP); // Where to start server
sinClient.sin_port = htons(80); //Port
if(connect(sClient, (LPSOCKADDR)&sinClient, sizeof(sinClient)) == SOCKET_ERROR)
{
/* failed at starting server */
printf("Could not connect ot the server!\n");
WSACleanup();
system("PAUSE");
return 1;
}
// Now we can send/recv data!
printf("YOU ARE CONNECTED!\r\n");
string buffer;
buffer += "GET / HTTP/1.1\r\n";
buffer += "Host: http://www.yahoo.com/\r\n";
buffer += "Connection: close\r\n\r\n";
const char *cha = buffer.c_str();
int sent;
int response;
sent = send(sClient, cha, sizeof(cha) - 1, 0);
char recvbuf[50000];
response = recv(sClient, recvbuf, 50000, 0);
recvbuf[response] = '\0';
printf("\nReceived data = %s", recvbuf);
WSACleanup();
return(0);
}
"sent" will get printed after the send function, but nothing after recv gets printed.
What am I missing here?

A possible cause is that the send() is not sending the data intended:
sent = send(sClient, cha, sizeof(cha) - 1, 0);
the sizeof(cha) - 1 is actually sizeof(char*) - 1, not the actual length of the data: use buffer.length() instead.
Note that you can construct the std::string with the string literal in a single statement instead of constructing it via several concatentations. However, as the std::string is being used to obtain a const char* only there is no reason for using std::string at all:
const char* buffer = "GET / HTTP/1.1\r\n"
"Host: http://www.yahoo.com/\r\n"
"Connection: close\r\n\r\n";
sent = send(sClient, buffer, strlen(buffer), 0);
Check the return value of send() and recv() to determine success or failure, particularly recv() as the result is being used to index an array. On failure, recv() returns SOCKET_ERROR which (I think) is -1.
Handling HTTP responses correctly requires significant effort. The receiving code needs to examine the returned HTTP headers to determine how to handle the response content. For example, a HTTP response may be chunked or not. Libraries exist for managing HTTP requests, one is cpp-netlib (which was announced on isocpp.org circa February 2013).

Related

Linux socket read() can not read the response body correctly

int proxyRequest(string &request, char buffer[], struct hostent* host){
int sockfd, sockopt;
struct sockaddr_in their_addr;
if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1){
perror("Socket generating failed");
return -1;
}
if(host==NULL){
strcpy(buffer, "HTTP/1.1 404 Not found\r\nContent-Type: text/html\r\n\r\n<h2>INET_E_RESOURCE_NOT_FOUND</h2>");
}
else{
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(SERVERPORT);
their_addr.sin_addr.s_addr = ((struct in_addr*)host->h_addr_list[0])->s_addr;
if(connect(sockfd, (struct sockaddr*)&their_addr, sizeof(their_addr)) == -1){
perror("Connection failed");
return -1;
}
write(sockfd, request.c_str(), request.length());
read(sockfd, buffer, BUFSIZE);
cout << buffer << endl;
}
close(sockfd);
return 0;
}
I am making a simple proxy server and everything's fine, except I can't receive a correct resposne body.
This is the request that I send to server(www.example.com). This is represented as "request" in the code.
It seems that http headers are received correctly. However, the html file(body) is not sent at all. And there is a weird character instead of it. Why does this happen? Is it related to null character?
However, the html file(body) is not sent at all. And there is a weird character instead of it. Why does this happen?
The body is sent, but compressed. The following tells you that the content is compressed using the gzip algorithm:
Content-Encoding: gzip
You'll need to either decompress it (taking care around NUL characters) or tell the server that you're not prepared to deal with gzip encoded content (i.e. remove the Accept-Encoding header in your request).

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.

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.

C++ - client-server application - recv() on server is functional, but recv() on client blocks program

I'm writing client-server application. Until now everything was OK, client sent a request, server recieved it, parse it. But now I want to send back an answer, so I copied those two functions, I put write() from client to server and read() from server to client. And when I run the program now everything blocks, server waits, client waits too. When I ctrl+c client, server unblocks and parse the right request and waits for another. What could be wrong, please?
Part of code from client:
params.port = atoi(params.pvalue.c_str());
hostent *host;
sockaddr_in socketHelper;
int clientSocket;
char buf[BUFFER_LEN];
int size;
string data;
string recieved;
// gets info about server
host = gethostbyname(params.hvalue.c_str());
if(host == NULL) {
printErr(ERR_HOSTNAME);
return ERR_HOSTNAME;
}
// makes a socket
if((clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
printErr(ERR_SOCKET);
return ERR_SOCKET;
}
socketHelper.sin_family = AF_INET;
socketHelper.sin_port = htons(params.port);
memcpy(&(socketHelper.sin_addr), host->h_addr, host->h_length);
// connects the socket
if(connect(clientSocket, (sockaddr *)&socketHelper, sizeof(socketHelper)) == -1) {
printErr(ERR_CONNECTION);
return ERR_CONNECTION;
}
// sends data
if((size = write(clientSocket, request.c_str(), request.length())) == -1) {
printErr(ERR_SEND);
return ERR_SEND;
}
// recieves data
while ((size = read(clientSocket, buf, BUFFER_LEN)) != 0) {
recieved.erase();
recieved.append(buf, size);
data = data + recieved;
}
// closes a connection
close(clientSocket);
And part of code from server:
while(1) {
int clientSocket = accept(GodParticle, (struct sockaddr*) &GodAddr, &clientSocketSize);
if(clientSocket == -1) {
printErr(ERR_ACCEPT);
return ERR_ACCEPT;
}
if((pid = fork()) == 0) {
while ((size = read(clientSocket, buf, BUFFER_LEN)) != 0) {
recieved.erase();
recieved.append(buf, size);
request = request + recieved;
}
parserInput(request);
getData();
parserOutput();
if((size = write(clientSocket, sendback.c_str(), sendback.length())) == -1) {
printErr(ERR_SEND);
return ERR_SEND;
}
close(clientSocket);
exit(ERR_OK);
}
}
Ok, let me answer in this way.
recv() is blocking your program by default until it receive some message from server.
And the reason why recv() does not blocks your server program is because you used fork() to create a child process.
So you have to use some other method to avoid this block(maybe like using select or some other things).

BSD Sockets - Using send and recv

I am trying to implement a simple chat program in linux using bsd sockets. Right now I am just trying to send and receive one message to the server from a client. Whenever I run the code, recv returns -1 and the errno code is 22.
Server code -
struct sockaddr name;
char buf[80];
int main(int agrc, char** argv) {
int sock, new_sd; //sock is this socket, new_sd is connection socket
int adrlen, cnt;
name.sa_family = AF_UNIX;
strcpy(name.sa_data, "/tmp/servsock");
adrlen = strlen(name.sa_data) + sizeof(name.sa_family);
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
cout<<"\nserver socket failure "<<errno;
cout<<"\nServer: ";
exit(1);
}
unlink("/tmp/servsock");
if(bind (sock, &name, adrlen) < 0)
cout<<"\nBind failure "<<errno;
if(listen(sock, 5) < 0)
cout<<"\nlisten error "<<errno;
while(1) {
if( new_sd = accept(sock, &name, (socklen_t*)&adrlen) < 0) {
cout<<"\nserver accept failure "<<errno;
exit(1);
}
char* buf = new char[14];
if(recv(sock, buf, 14, 0) < 0) {
cout<<"\nError receiving data "<<errno;
exit(1);
}
} //end while
return 0;
}
Client code -
struct sockaddr name;
int main(int agrc, char** argv) {
int sock, new_sd, adrlen, cnt;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
cout<<"\nserver socket failure "<<errno;
cout<<"\nServer: ";
exit(1);
}
//stuff for server socket
name.sa_family = AF_UNIX;
strcpy(name.sa_data, "/tmp/servsock");
adrlen = strlen(name.sa_data) + sizeof(name.sa_family);
if(connect(sock, &name, adrlen) < 0) {
cout<<"\nclient connection failure "<<errno;
exit(1);
}
cout<<"\nSuccessful connection from client 1";
std::string buf = "\nClient 1 Here";
if(send(sock, buf.c_str(), strlen(buf.c_str()), 0) < 0) {
cout<<"\nError sending data from client 1 "<<errno;
exit(1);
}
cout<<"\nExiting normally";
return 0;
}
Even though I get the error on the server side, I do not get the error message on the client side - it just exits normally.
According to - http://www.workers.com.br/manuais/53/html/tcp53/mu/mu-7.htm the errno 22 error message just means "Invalid argument". But I don't know how exactly to interpret that...if an argument was invalid why would it even compile?
If anyone can point out what I'm doing wrong here I would be very grateful. And any other small notes you feel like pointing out would be welcomed. Thanks for any help.
Aside from all other problems in your code, you are trying to read on the wrong file descriptor - it should be new_sd, not sock, which is a server socket and can only accept() new connections.
Edit 0:
Big boo-boo:
if( new_sd = accept(sock, &name, (socklen_t*)&adrlen) < 0) { ...
This is equivalent to:
if( new_sd = (accept(sock, &name, (socklen_t*)&adrlen) < 0)) {
So new_sd gets totally wrong value. General wisdom is not to put assignments into conditionals. Consider compiling with high warning levels, at least -Wall -pedantic.
One thing that looks wrong in your code is that you're recving on sock when you should be recving from new_fd. Not sure why that would give EINVAL though.
(EINVAL errors are (usually) not detectable at compile time. File descriptors are plain ints. The compiler cannot know which ints are valid file descriptors at runtime, or if a particular combination of flags is valid for the sockets you're using for instance.)
In the'recv()' call (in the server), the 'flags' parameter can't be 0:
recv(sock, buf, 14, 0)
Try something like:
recv(sock, buf, 14, MSG_WAITALL)
See the 'man' page for the whole list of options for 'flags' parameter. One must be judicious here on how the message is to be received.
The reason why the client doesn't get the error message (INVALID ARG) is because it doesn't do any recv's ... only the server is doing receive's.