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).
6 Comments
good
ReplyDeleteIts working great
DeleteWhat is 'www.dhanoop.com' while executing server?
ReplyDeleteHi,
DeleteIt's just a name (domain name). It has NO significance. You can use any name.
Is the IP address '192.168.0.6, for www.dhanoop.com
ReplyDeleteHi,
Deletewww.dhanoop.com is just a name given. You can replace it with anything. That IP address is my machine's IP in the local network. Replace it with your IP while running the program.