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.