This is my code for web-server.cpp file
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cerrno>
#include <cstring>
#include <netdb.h>
#include <csignal>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include "httpResponse.h"
#define BACKLOG 10
#define MESSAGE_SIZE 1000000
using namespace std;
bool writeDataToClient(int socket, const char *data, int datalen)
{
const char *pdata = data;
while (datalen > 0)
{
int numSent = send ( socket, pdata, datalen, 0 );
if (numSent <= 0)
{
if (numSent == 0)
{
printf("The client was not written to: disconnected\n");
}
else
{
perror("The client was not written to");
}
return false;
}
pdata += numSent;
datalen -= numSent;
}
return true;
}
bool writeStrToClient(int sckt, const char *str)
{
return writeDataToClient(sckt, str, strlen(str));
}
void respond ( int n, char buffer[MESSAGE_SIZE], int *sock_clients, char* path)
{
char mesg[MESSAGE_SIZE], *reqline[3], data_to_send[MESSAGE_SIZE] ;
int rcvd, fd, bytes_read;
memset(mesg, 0, MESSAGE_SIZE);
strcpy( mesg, buffer);
printf("%s", mesg);
reqline[0] = strtok ( mesg, " \t\n");
if ( strncmp ( reqline[0], "GET\0", 4) == 0 )
{
reqline[1] = strtok (NULL, " \t") ;
reqline[2] = strtok (NULL, " \t\n") ;
if ( strncmp( reqline[2], "HTTP/1.0", 8) != 0 && strncmp ( reqline[2], "HTTP/1.1", 8) != 0 )
{
httpResponse response(400, "");
writeDataToClient(sock_clients[n], response.fullResponse.c_str(), response.getResponseLength());
}
else
{
if ( strncmp(reqline[1], "/\0", 2) == 0 )
{
reqline[1] = (char*)"/index.html";
}
strcpy(&path[strlen(path)], reqline[1]);
printf("file: %s\n", path);
if ( ( fd = open ( path, O_RDONLY) ) != -1 )
{
bytes_read=read(fd, data_to_send, MESSAGE_SIZE);
httpResponse response(200, data_to_send);
if (!writeDataToClient(sock_clients[n], response.fullResponse.c_str(), response.getResponseLength() ) )
{
{
close(sock_clients[n]);
}
}
}
else
{
httpResponse response(404, "");
writeDataToClient(sock_clients[n], response.fullResponse.c_str(), response.getResponseLength());
}
}
}
shutdown ( sock_clients[n], SHUT_RDWR );
close(sock_clients[n]);
sock_clients[n]=0;
return;
}
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 ( int argc, char** argv )
{
struct addrinfo hints, *serverinfo, *p ;
struct sockaddr_storage client_addr;
char *path;
int addr;
int sock, sock_new, sock_clients[30], max_clients = 30, max_sd, sd, activity, valread ;
fd_set readfds;
char buffer[1025];
int yes = 1;
path = new char( strlen(argv[3]) );
strcpy(path, argv[3]) ;
printf("\n path is %s \n " , path );
for (int i = 0; i < max_clients; i++)
{
sock_clients[i] = 0;
}
memset( &hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if( ( addr = getaddrinfo( argv[1], argv[2], &hints, &serverinfo ) ) != 0 )
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(addr));
return 1;
}
p = serverinfo;
printf("\np->ai_addr %c " , p -> ai_addr->sa_data[0] ) ;
while( p != NULL)
{
if( ( sock = socket ( p->ai_family, p->ai_socktype, p->ai_protocol) ) == -1 )
{
perror("Error: socket");
continue;
}
if ( setsockopt ( sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int) ) == -1 )
{
perror("Error: setsockopt");
exit(1);
}
if ( ( bind ( sock, p->ai_addr, p->ai_addrlen) ) == -1 )
{
printf("\nhello\n") ;
close(sock);
perror("Error: bind");
p = p->ai_next;
continue;
}
break;
}
if ( p == NULL )
{
fprintf(stderr, "Failed to bind\n");
exit(1);
}
if( listen ( sock, BACKLOG)== -1 )
{
perror("Error: Listen");
exit(1);
}
int addrlen = sizeof(client_addr);
cout<<"Waiting for connections.."<<endl;
while(1)
{
FD_ZERO(&readfds);
FD_SET(sock, &readfds);
max_sd = sock;
for (int i = 0 ; i < max_clients ; i++)
{
sd = sock_clients[i];
if ( sd > 0 )
{
FD_SET( sd , &readfds);
}
if ( sd > max_sd )
{
max_sd = sd;
}
}
activity = select( max_sd + 1 , &readfds , NULL , NULL , NULL);
if ( (activity < 0) && (errno!=EINTR) )
{
printf("select error");
}
if ( FD_ISSET(sock, &readfds))
{
if ( (sock_new = accept(sock, (struct sockaddr *)&client_addr, (socklen_t*)&addrlen) )<0 )
{
perror("accept");
exit(1);
}
puts ( "Welcome message sent successfully");
for (int i = 0; i < max_clients; i++)
{
if( sock_clients[i] == 0 )
{
sock_clients[i] = sock_new;
printf("Adding to list of sockets as %d\n" , i);
break;
}
}
}
for (int i = 0; i < max_clients; i++)
{
sd = sock_clients[i];
if ( FD_ISSET( sd , &readfds) )
{
memset(path, 0, strlen(path));
strcpy ( path, argv[3]);
if ( (valread = read( sd , buffer, 1024)) == 0)
{
getpeername(sd , (struct sockaddr*)&client_addr , (socklen_t*)&addrlen);
close( sd );
sock_clients[i] = 0;
}
else
{
buffer[valread] = '\0';
respond(i, buffer, sock_clients, path);
}
}
}
}
return 0;
}
What I have tried:
I am trying to implement HTTP client server using socket programming in C.
When I run my web server the bind() function is unable to assign the request address. I don't know why.
I am trying to implement GET request method of http.
To run the client and server on linux terminal I do the following :
g++ -o abc.exe httpRequest.cpp web-client.cpp
g++ -o def.exe httpResponse.cpp web-server.cpp
./abc.exe http://www.google.com/earth/index.html
./def.exe www.google.com 80 /earth/index.html
I want to know what is going wrong in my program.
Any help is appreciated. Thanks.