How to receive and parse requests as an HTTP server? - c++

For a class I have to implement an HTTP web server in C++. I currently have the server to the point that it can listen and accept connections, but I can't figure out how to accept data and parse it. When I send a request I get an error saying "Transport endpoint is nt connected." Here's what my code looks like so far:
int main(int argc, char *argv[]) {
// parse CLI args
if (argc != 3) { /** change to 3 once DOCROOT is added */
cout << "invalid arguments" << endl;
exit(1);
}
const char *DOCROOT = argv[1];
const char *PORT = argv[2];
// declare vars....from beej's so some not in use yet
int sockfd, new_fd;
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr;
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;
// try getaddrinfo
if ((rv = getaddrinfo(nullptr, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through getaddrinfo response and bind when possible
for (p=servinfo; p!=nullptr; 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);
if (p == nullptr) {
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
/** choose backlog number and declare constant */
if (listen(sockfd, 5) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, nullptr) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections on port %s...\n", PORT);
while(true) { /** this will be the main accept loop */
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
// receive
char recvbuf[1024];
int recvbuflen = 1024;
int request = recv(sockfd, recvbuf, recvbuflen, 0);
if (request == -1) perror("error receiving data");
if(send(new_fd, "Data received", 15, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
return 0;
}

Related

TCP sockets (client-server) recv() returning -1 value

Please guide me why is blocking function recv() not waiting for message from client. Instead it is returning value -1. Please guide me how to resolve this issue.
Server code (partial):
(call to getaddrinfo) // struct addrinfo hints, *res
int sfd = socket(res->ai_family, res->ai_socktype,res->ai_protocol);
if(sfd == -1)
{
printf("Socket creation failed .....");
exit(-3);
}
fcntl(sfd, F_SETFL, ~O_NONBLOCK);
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)) < 0)
{
herror("setsockopt(SO_REUSEADDR) failed");
}
bind(sfd,res->ai_addr, res->ai_addrlen);
if(listen(sfd, BACKLOG)!=0)
{
printf("Listen Error");
exit(-4);
}
printf("\n\nListening on port: %s\n\n", argv[1]);
struct sockaddr_storage clientAddr;
socklen_t addrSize = sizeof(clientAddr);
int connFD = accept(sfd,(struct sockaddr*)&clientAddr, &addrSize); // connection successful
char buffer[10] = "Hello!";
write(connFD, buffer, sizeof(buffer)); // message sent to client
buffer[0] = '\0';
int bytesReceived;
if((bytesReceived = recv(sfd, buffer, sizeof(buffer), 0)) == -1) // Problem starts here
{
fprintf(stderr,"Could not retrieve message from client.");
exit(-5);
}
the problem is that you are calling recv on wrong socket (sfd) should be (connFD)
fix:
if((bytesReceived = recv(connFD, buffer, sizeof(buffer), 0)) == -1)

How to establish custom message passing from AWS Ubuntu Virtual Machine to local PC

I am trying to set up a simple client-server system for message passing, using a local PC and a cloud virtual machine (Ubuntu 16) hosted by AWS. It's quite basic right now and will be extended using e.g. protobuf, but right now it's about creating a basic working example before I start integrating the communication scheme into my actual program.
The 'server' waits for a request from the 'client', and will then send the data to the client. The client is given the IP address of the server on startup.
If I run the server part on my AWS virtual machine and the client part on my local PC, everything works perfect, the data is transferred. However, it does not work the other way round, I cannot reach my local PC from the AWS virtual machine. I'm pretty sure AWS security groups are correct, since it works with the server running in the virtual machine. Also the IP of the local machine should be correct, since when running the server on the virtual machine, it output the IP of the client that requested the data.
I searched before in some forums, and I figured out it seems generally more complicated to reach the local PC from the AWS virtual machine. However, I didn't find a solution to my problem, and I assume it must be possible to send data from a cloud virtual machine to a local PC...
Thanks for any help!
***** Client side *****
-- call client with IP of server as arg --
#define PORT "3490" // the port client will be connecting to
int main(int argc, char *argv[])
{
int sockfd, numbytes;
unsigned char buf[MAXDATASIZE];
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and connect 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) {
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
continue;
}
break;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo);
if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
exit(1);
}
//deserialize and output data -- omitted
return 0;
}
***** Server side *****
int main(void)
{
srand (time(NULL));
mydata md0; //data structure that will be sent
//write members of md0 -- omitted
unsigned char buf[MAXDATASIZE],*ptr;
ptr = Serialize_mydata(buf,&md0);
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) {
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
continue;
}
break;
}
freeaddrinfo(servinfo); // all done with this structure
if (listen(sockfd, BACKLOG) == -1) {
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
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);
if (new_fd == -1) {
continue;
}
inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
if (send(new_fd, buf, ptr - buf, 0) == -1)
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
return 0;
}

Server only receiving null string from client? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
So I have a basic client/server c++ program. Right now, when the client connects to the server I want the server sends a "Hello, world" message and the client to respond "Hello, server" just to make sure I am sending and relieving messages correctly.
When I run, the client receives the message from the server, but the server only receives a null string from the client.
Here is the code for the client
int main(int argc, char *argv[]) {
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
if (argc != 2) {
fprintf(stderr,"usage: client hostname\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and connect 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("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: connect");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
return 2;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
if (send(sockfd, "Hello, client!", 13, 0) == -1) {
perror("send");
}
buf[numbytes] = '\0';
printf("client: received '%s'\n",buf);
close(sockfd);
return 0;
}
and Here's the code for the server
int main(void)
{
int sockfd, new_fd, numbytes; // listen on sock_fd, new connection on new_fd
char buf[MAXDATASIZE];
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);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
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);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
if (send(new_fd, "Hello, world!", 13, 0) == -1)
perror("send");
if (numbytes = recv(new_fd, &buf, MAXDATASIZE-1, 0) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("server: received '%s'\n",buf);
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
return 0;
}
Now I figured it out:
if (numbytes = recv(new_fd, &buf, MAXDATASIZE-1, 0) == -1) {
recv(new_fd, &buf, MAXDATASIZE-1, 0) == -1 is 0 on success and 1 on error. And that gets assigned to numbytes. So, you want to add parenthesises like this:
if ((numbytes = recv(new_fd, &buf, MAXDATASIZE-1, 0)) == -1) {
Or you want to split it into two lines like this:
numbytes = recv(new_fd, &buf, MAXDATASIZE-1, 0);
if (numbytes == -1) {
Oh and next time plz decide for either C or C++, both are different languages.

daemon socket listening in background for request

I have two process: daemon and client. Both are different sockets. Initially I execute deamon socket by
./daemon and then ./client.
But I wanted that daemon process should listen in background always for the request from client. So using fork() I tried to create such a process.
I just edited the original code.
Now when I can compile daemon files and create executable daemon.
But when I send request ./client it does not respond. And says error connecting socket 111.
daemon is listening on 1104 and client sending request on the same.
When I exucte ./daemon it says
Error binding to socket, make sure nothing else is listening on this port 22n
Means it running in the back ground but not responding on request.
Code:
#include <fcntl.h>
#include <string.h>
#include <algorithm>
#include "dictionary_exclude.h"
#pragma GCC diagnostic ignored "-Wwrite-strings"
#define CHECK_THROW(condition, code) if(condition) throw code
void *SocketHandler(void *);
int OpenSocket();
int main(int argv, char **argc)
{
int host_port = 1104;
char buf[20];
int k;
struct sockaddr_in my_addr;
int hsock;
int *p_int;
int err;
socklen_t addr_size = 0;
int *csock;
sockaddr_in sadr;
pthread_t thread_id = 0;
try {
pid_t pid = fork();
CHECK_THROW(pid < 0, -5);
if (pid == 0) {
mode_t umask(mode_t mask);
pid_t childid = setsid();
hsock = OpenSocket(); // Function call for hsock
CHECK_THROW(listen(hsock, 10) == -1, -4);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(hsock, (sockaddr *) & my_addr, sizeof(my_addr)) == -1) {
fprintf(stderr, "Error binding to socket, make sure nothing else is listening on this port %dn", errno);
exit(EXIT_SUCCESS);
}
if (listen(hsock, 10) == -1) {
fprintf(stderr, "Error listening %dn", errno);
exit(EXIT_SUCCESS);
}
//Now lets do the server stuff
addr_size = sizeof(sockaddr_in);
while (true) {
printf("waiting for a connectionnn");
csock = (int *) malloc(sizeof(int));
if ((*csock = accept(hsock, (sockaddr *) & sadr, &addr_size)) != -1) {
printf("---------------------nReceived connection from %sn", inet_ntoa(sadr.sin_addr));
pthread_create(&thread_id, 0, &SocketHandler, (void *) csock);
pthread_detach(thread_id);
} else {
fprintf(stderr, "Error accepting %dn", errno);
}
} //while end
} //if (pid) end
} //try
catch(int ierror) {
switch (ierror) {
case -4:
fprintf(stderr, "Error listening %dn", errno);
break;
case -7:
fprintf(stderr, "Error accepting %dn", errno);
break;
}
}
}
int OpenSocket()
{
// Create your socket and return the socket handle from this function
int hsock;
int *p_int;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if (hsock == -1) {
printf("Error initializing socket %dn", errno);
exit(EXIT_SUCCESS);
}
p_int = (int *) malloc(sizeof(int));
*p_int = 1;
if ((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char *) p_int, sizeof(int)) == -1) || (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char *) p_int, sizeof(int)) == -1)) {
printf("Error setting options %dn", errno);
free(p_int);
exit(EXIT_SUCCESS);
}
free(p_int);
return hsock;
}
void *SocketHandler(void *lp)
{
//some procesing
}
Can some one say is there any problem in above code.
Original code was:
int main(int argv, char **argc)
{
int host_port = 1104;
char buf[20];
int k;
struct sockaddr_in my_addr;
int hsock;
int *p_int;
int err;
socklen_t addr_size = 0;
int *csock;
sockaddr_in sadr;
pthread_t thread_id = 0;
try {
pid_t pid = fork();
CHECK_THROW(pid < 0, -5);
if (pid == 0) {
mode_t umask(mode_t mask);
pid_t childid = setsid();
hsock = OpenSocket(); // Function call for hsock
CHECK_THROW(listen(hsock, 10) == -1, -4);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(hsock, (sockaddr *) & my_addr, sizeof(my_addr)) == -1) {
fprintf(stderr, "Error binding to socket, make sure nothing else is listening on this port %dn", errno);
exit(EXIT_SUCCESS);
}
if (listen(hsock, 10) == -1) {
fprintf(stderr, "Error listening %dn", errno);
exit(EXIT_SUCCESS);
}
//Now lets do the server stuff
addr_size = sizeof(sockaddr_in);
while (true) {
printf("waiting for a connectionnn");
csock = (int *) malloc(sizeof(int));
if ((*csock = accept(hsock, (sockaddr *) & sadr, &addr_size)) != -1) {
printf("---------------------nReceived connection from %sn", inet_ntoa(sadr.sin_addr));
pthread_create(&thread_id, 0, &SocketHandler, (void *) csock);
pthread_detach(thread_id);
} else {
fprintf(stderr, "Error accepting %dn", errno);
}
} //while end
} //if (pid) end
} //try
catch(int ierror) {
switch (ierror) {
case -4:
fprintf(stderr, "Error listening %dn", errno);
break;
case -7:
fprintf(stderr, "Error accepting %dn", errno);
break;
}
}
}
int OpenSocket()
{
// Create your socket and return the socket handle from this function
int hsock;
int *p_int;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if (hsock == -1) {
printf("Error initializing socket %dn", errno);
exit(EXIT_SUCCESS);
}
p_int = (int *) malloc(sizeof(int));
*p_int = 1;
if ((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char *) p_int, sizeof(int)) == -1) || (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char *) p_int, sizeof(int)) == -1)) {
printf("Error setting options %dn", errno);
free(p_int);
exit(EXIT_SUCCESS);
}
free(p_int);
return hsock;
}
void *SocketHandler(void *lp)
{
//some procesing
}
You are calling listen before you call bind - you should call bind first.
Actually, you are calling listen twice, both before and after calling bind. Remove the first call.
hsock = OpenSocket();
// remove this line:
CHECK_THROW(listen(hsock, 10) == -1, -4);
my_addr.sin_family = AF_INET;
Another improvement: use strerror or perror to generate the error message so that you get a user friendly message. For example:
perror("Error binding to socket");
exit(EXIT_SUCCESS);
The solution was pretty easy:
No need for big coding, just & will do everything.
inplace of executing ./daemon use ./daemon &. This will keep daemon processing listening in back

Error connecting to server by proxy server in c++ socket programming

The code for connection :
cout << "connecting1\n";
WSADATA wsadata;
int iResult = WSAStartup (MAKEWORD(2,2), &wsadata );
if (iResult !=NO_ERROR )
printf("\nmyERROR at WSAStartup()\n");
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
perror("error opening socket"); return -1;
}
struct sockaddr_in sin;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = inet_addr(host.c_str());
sin.sin_family = AF_INET;
if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
perror("error connecting to host"); return -1;
}
const int query_len = query.length() + 1; // trailing '\0'
if (send(sock, query.c_str(), query_len, 0) != query_len) {
perror("error sending query"); return -1;
}
const int buf_size = 1024 * 1024;
while (true) {
std::vector<char> buf(buf_size, '\0');
const int recv_len = recv(sock, &buf[0], buf_size - 1, 0);
if (recv_len == -1) {
perror("error receiving response"); return -1;
} else if (recv_len == 0) {
std::cout << std::endl; break;
} else {
std::cout << &buf[0];
fprintf(fp, "%s", &buf[0]);
}
}
In wifi without proxy it works fine, but when we use proxy server, net can be accessed in chrome, but the above code prints
connecting1
error connecting to host
What is the problem ?