The HTTP server sends the files requested by the client, if it is available at the server. The HTTP client uses GET method for requesting files from the server. Only .html, .txt and .pdf files are implemented. On receiving the file, the client program opens it using firefox or gedit or acrobat reader, as per the file type. Note that the given programs were done in Linux (Debian) environment.
httpserver.c
/**httpserver.c**/
#include"stdio.h"
#include"stdlib.h"
#include"sys/types.h"
#include"sys/socket.h"
#include"string.h"
#include"netinet/in.h"
#include"time.h"
#include"dirent.h"
#include"netdb.h"
#define BUF_SIZE 1024
#define CLADDR_LEN 100
int createSocket(char * host, int port);
int listenForRequest(int sockfd);
char * getFileType(char * file);
int main(int argc, char **argv) {
DIR * dirptr;
FILE * fileptr;
time_t timenow;
struct tm * timeinfo;
time (&timenow);
timeinfo = localtime(&timenow);
char * header, * request, * path, * newpath, * host;
char * dir, * temp;
int port, sockfd, connfd;
char get[3], http[9];
char filepath[BUF_SIZE];
char http_not_found[] = "HTTP/1.0 404 Not Found\n";
char http_ok[] = "HTTP/1.0 200 OK\n";
char buffer[BUF_SIZE];
char * contentType;
if (argc != 4) {
printf("usage: [host] [directory] [portnumber]\n");
exit(1);
}
header = (char*)malloc(BUF_SIZE*sizeof(char));
request = (char*)malloc(BUF_SIZE*sizeof(char));
path = (char*)malloc(BUF_SIZE*sizeof(char));
newpath = (char*)malloc(BUF_SIZE*sizeof(char));
host = argv[1];
dir = argv[2];
port = atoi(argv[3]);
if ((dirptr = opendir(dir)) == NULL) {
printf("Directory Not Found!\n");
exit(1);
}
sockfd = createSocket(host, port);
for (;;) {
printf("--------------------------------------------------------\n");
printf("Waiting for a connection...\n");
connfd = listenForRequest(sockfd);
//gets the request from the connection
recv(connfd, request, 100, 0);
printf("Processing request...\n");
//parses request
sscanf(request, "%s %s %s", get, path, http);
newpath = path + 1; //ignores the first slash
sprintf(filepath,"%s/%s", dir, newpath);
contentType = getFileType(newpath);
sprintf(header, "Date: %sHostname: %s:%d\nLocation: %s\nContent-Type: %s\n\n", asctime(timeinfo), host, port, newpath, contentType);
if ((fileptr = fopen(filepath, "r")) == NULL ) {
printf("File not found!\n");
send(connfd, http_not_found, strlen(http_not_found), 0); //sends HTTP 404
} else {
printf("Sending the file...\n");
send(connfd, http_ok, strlen(http_ok), 0); //sends HTTP 200 OK
recv(connfd, buffer, BUF_SIZE, 0);
if ((temp = strstr(buffer, "OK")) == NULL) {
printf("Operation aborted by the user!\n");
break;
}
send(connfd, header, strlen(header), 0); //sends the header
recv(connfd, buffer, BUF_SIZE, 0);
if ((temp = strstr(buffer, "OK")) == NULL) {
printf("Operation aborted by the user!\n");
break;
}
memset(&buffer, 0, sizeof(buffer));
while (!feof(fileptr)) { //sends the file
fread(&buffer, sizeof(buffer), 1, fileptr);
send(connfd, buffer, sizeof(buffer), 0);
memset(&buffer, 0, sizeof(buffer));
}
printf("File sent...\n");
}
printf("Processing completed...\n");
close(connfd);
}
close(sockfd);
free(header);
free(request);
free(path);
free(newpath);
return 0;
}
int createSocket(char * host, int port) {
int sockfd;
struct sockaddr_in addr;
struct hostent * host_ent;
char * hostAddr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons((short)port);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket!\n");
exit(1);
}
printf("Socket created...\n");
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
printf("Error binding socket to port!\n");
exit(1);
}
printf("Binding done...\n");
return sockfd;
}
int listenForRequest(int sockfd) {
int conn;
char hostip[32];
struct sockaddr_in addr;
struct hostent * host;
struct in_addr inAddr;
int len;
addr.sin_family = AF_INET;
listen(sockfd, 5); //maximum 5 connections
len = sizeof(addr);
if ((conn = accept(sockfd, (struct sockaddr *)&addr, &len)) < 0) {
printf("Error accepting connection!\n");
exit(1);
}
printf("Connection accepted...\n");
inet_ntop(AF_INET, &(addr.sin_addr), hostip, 32);
inet_pton(AF_INET, hostip, &inAddr);
host = gethostbyaddr(&inAddr, sizeof(inAddr), AF_INET);
printf("---Connection received from: %s [IP= %s]---\n", host->h_name, hostip);
return conn;
}
char * getFileType(char * file) {
char * temp;
if ((temp = strstr(file, ".html")) != NULL) {
return "text/html";
} else if ((temp = strstr(file, ".pdf")) != NULL) {
return "application/pdf";
} else if ((temp = strstr(file, ".txt")) != NULL) {
return "text/html";
}
}
httpclient.c
/**httpclient.c**/
#include"stdio.h"
#include"stdlib.h"
#include"sys/types.h"
#include"sys/socket.h"
#include"string.h"
#include"netinet/in.h"
#include"netdb.h"
#define BUF_SIZE 1024
int get_request(char * url, char * port);
int isValidIP(char * ip);
int parseHeader(char * header);
char * splitKeyValue(char * line, int index);
void openFile();
FILE * fileptr;
char keys[][25] = {"Date: ", "Hostname: ", "Location: ", "Content-Type: "};
char status[4] = {0, 0, 0, 0};
char contentFileType[100];
char path[1000];
int main(int argc, char**argv) {
struct sockaddr_in addr, cl_addr;
int sockfd, ret;
struct hostent * server;
char * url, * temp;
int portNumber;
char * fileName;
char status_ok[] = "OK";
char buffer[BUF_SIZE];
char http_not_found[] = "HTTP/1.0 404 Not Found";
char http_ok[] = "HTTP/1.0 200 OK";
char location[] = "Location: ";
char contentType[] = "Content-Type: ";
int sPos, ePos;
if (argc < 3) {
printf("usage: [URL] [port number]\n");
exit(1);
}
url = argv[1];
portNumber = atoi(argv[2]);
//checking the protocol specified
if ((temp = strstr(url, "http://")) != NULL) {
url = url + 7;
} else if ((temp = strstr(url, "https://")) != NULL) {
url = url + 8;
}
//checking the port number
if (portNumber > 65536 || portNumber < 0) {
printf("Invalid Port Number!");
exit(1);
}
sockfd = get_request(url, argv[2]);
memset(&buffer, 0, sizeof(buffer));
ret = recv(sockfd, buffer, BUF_SIZE, 0);
if (ret < 0) {
printf("Error receiving HTTP status!\n");
} else {
printf("%s\n", buffer);
if ((temp = strstr(buffer, http_ok)) != NULL) {
send(sockfd, status_ok, strlen(status_ok), 0);
} else {
close(sockfd);
return 0;
}
}
memset(&buffer, 0, sizeof(buffer));
ret = recv(sockfd, buffer, BUF_SIZE, 0);
if (ret < 0) {
printf("Error receiving HTTP header!\n");
} else {
printf("%s\n", buffer);
if (parseHeader(buffer) == 0) {
send(sockfd, status_ok, strlen(status_ok), 0);
} else {
printf("Error in HTTP header!\n");
close(sockfd);
return 0;
}
}
//printf("file: [%s]\n", fileName);
fileptr = fopen(path, "w");
if (fileptr == NULL) {
printf("Error opening file!\n");
close(sockfd);
return 0;
}
memset(&buffer, 0, sizeof(buffer));
while (recv(sockfd, buffer, BUF_SIZE, 0) > 0) { //receives the file
if ((strstr(contentFileType, "text/html")) != NULL) {
fprintf(fileptr, "%s", buffer);
} else {
fwrite(&buffer, sizeof(buffer), 1, fileptr);
}
memset(&buffer, 0, sizeof(buffer));
}
fclose(fileptr);
close(sockfd);
openFile();
return 0;
}
int get_request(char * url, char * port) {
int sockfd, bindfd;
char * ptr, * host;
char getrequest[1024];
struct sockaddr_in addr;
if (isValidIP(url)) { //when an IP address is given
sprintf(getrequest, "GET / HTTP/1.0\nHOST: %s\n\n", url);
} else { //when a host name is given
if ((ptr = strstr(url, "/")) == NULL) {
//when hostname does not contain a slash
sprintf(getrequest, "GET / HTTP/1.0\nHOST: %s\n\n", url);
} else {
//when hostname contains a slash, it is a path to file
strcpy(path, ptr);
host = strtok(url, "/");
sprintf(getrequest, "GET %s HTTP/1.0\nHOST: %s\n\n", path, url);
}
}
// creates a socket to the host
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket!\n");
exit(1);
}
printf("Socket created...\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(url);
addr.sin_port = htons(atoi(port));
if (connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0 ) {
printf("Connection Error!\n");
exit(1);
}
printf("Connection successful...\n\n\n");
ptr = strtok(path, "/");
strcpy(path, ptr);
//printf("path=%s\n", path);
//fileptr = fopen(path, "w");
//strcpy(fileName, path);
//sprintf(fileName, "%s", path);
//int optval = 1;
//setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
// writes the HTTP GET Request to the sockfd
write(sockfd, getrequest, strlen(getrequest));
return sockfd;
}
int isValidIP(char * ip) {
struct sockaddr_in addr;
int valid = inet_pton(AF_INET, ip, &(addr.sin_addr));
return valid != 0;
}
int parseHeader(char * header) {
//"Date: %sHostname: %s:%d\nLocation: %s\nContent-Type: %s\n\n"
char * line, * key, * value;
char temp[100];
int i = 0;
line = strtok(header, "\n");
while (line != NULL) {
//printf("%s\n", line);
strcpy(temp, line);
value = splitKeyValue(line, i);
if (i == 3) {
strcpy(contentFileType, value);
}
//printf("value=%s\n", value);
line = strtok(NULL, "\n");
i++;
}
for (i = 0; i < 4; i++) {
if (status[i] == 0) return 1;
//printf("status[%d]=%d\n", i, status[i]);
}
return 0;
}
char * splitKeyValue(char * line, int index) {
char * temp;
if ((temp = strstr(line, keys[index])) != NULL) {
temp = temp + strlen(keys[index]);
status[index] = 1;
}
return temp;
}
void openFile() {
char * temp;
char command[100];
char fileName[1000];
strcpy(fileName, path);
//printf("File Name: %s\n", fileName);
//printf("Content Type: %s\n", contentFileType);
if ((temp = strstr(contentFileType, "text/html")) != NULL) {
if ((temp = strstr(fileName, ".txt")) != NULL) {
sprintf(command, "gedit %s", fileName);
} else {
sprintf(command, "firefox %s", fileName);
}
system(command);
} else if ((temp = strstr(contentFileType, "application/pdf")) != NULL) {
sprintf(command, "acroread %s", fileName);
system(command);
} else {
printf("The filetype %s is not supported. Failed to open %s!\n", contentFileType, fileName);
}
}
Execution:
(terminal 1)
gcc httpserver.c -o server
./server 'www.dhanoop.com' '/home/dhanoopbhaskar/coding/http/dir/' 4444
(terminal 2)
gcc httpclient.c -o client
./client '192.168.0.6/abc.txt' 4444
./client '192.168.0.6/abc.html' 4444
./client '192.168.0.6/abc.pdf' 4444
NB: The requested files abc.txt, abc.html and abc.pdf should be present in the path /home/dhanoopbhaskar/coding/http/dir/
(or whatever is given while running server).