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
httpclient.c
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).
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).