pritam123456
asked on
A web server for Unix
Here is the code for a web server:
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <curses.h>
#include <sys/time.h>
#include <netdb.h>
#define MAXLINE 1000
#define SA struct sockaddr
#define DOCUMENT "index.html"
void
sigchld_handler(int s)
{
while (wait(NULL) > 0);
}
void
send_doc(int connfd)
{
FILE *fp;
char output[1000];
int len;
if((fp = fopen(DOCUMENT, "r")) == NULL) {
printf("Cannot open file.\n");
exit(1);
}
while(!feof(fp)) {
fgets(output, 999, fp);
len = strlen(output);
if (sendall(connfd, output, &len) == -1) {
perror("sendall");
printf("We only sent %d bytes because of the error!\n", len);
}
}
}
int
sendall(int s, char *buf, int *len)
{
int total = 0;
int bytesleft = *len;
int n;
while (total < *len) {
n = send(s, buf + total, bytesleft, 0);
if (n == -1) {
break;
}
total += n;
bytesleft -= n;
}
*len = total;
return n == -1 ? -1 : 0;
}
int
main(void)
{
int listenfd, connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
struct sigaction sa;
int len, yes = 1, sin_size, nbytes;
char data[1000];
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if ((connfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(8080);
if (bind(listenfd, (struct sockaddr *) & servaddr, sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
if (listen(listenfd, 10) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
for (;;) {
clilen = sizeof(cliaddr);
if ((connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) == -1) {
perror("accept");
exit(1);
}
printf("server: got connection from %s\n", inet_ntoa(cliaddr.sin_addr ));
if ((childpid = fork()) == 0) {
close(listenfd);
send_doc(connfd);
sleep(10);
exit(0);
}
close(connfd);
}
}
It is working properly. it is displaying index.html as default which is in the root directory. now i want to modify the code so that it can display any requested page stored in the root folder.? how will i do that??
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <curses.h>
#include <sys/time.h>
#include <netdb.h>
#define MAXLINE 1000
#define SA struct sockaddr
#define DOCUMENT "index.html"
void
sigchld_handler(int s)
{
while (wait(NULL) > 0);
}
void
send_doc(int connfd)
{
FILE *fp;
char output[1000];
int len;
if((fp = fopen(DOCUMENT, "r")) == NULL) {
printf("Cannot open file.\n");
exit(1);
}
while(!feof(fp)) {
fgets(output, 999, fp);
len = strlen(output);
if (sendall(connfd, output, &len) == -1) {
perror("sendall");
printf("We only sent %d bytes because of the error!\n", len);
}
}
}
int
sendall(int s, char *buf, int *len)
{
int total = 0;
int bytesleft = *len;
int n;
while (total < *len) {
n = send(s, buf + total, bytesleft, 0);
if (n == -1) {
break;
}
total += n;
bytesleft -= n;
}
*len = total;
return n == -1 ? -1 : 0;
}
int
main(void)
{
int listenfd, connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
struct sigaction sa;
int len, yes = 1, sin_size, nbytes;
char data[1000];
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if ((connfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(8080);
if (bind(listenfd, (struct sockaddr *) & servaddr, sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
if (listen(listenfd, 10) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
for (;;) {
clilen = sizeof(cliaddr);
if ((connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) == -1) {
perror("accept");
exit(1);
}
printf("server: got connection from %s\n", inet_ntoa(cliaddr.sin_addr
if ((childpid = fork()) == 0) {
close(listenfd);
send_doc(connfd);
sleep(10);
exit(0);
}
close(connfd);
}
}
It is working properly. it is displaying index.html as default which is in the root directory. now i want to modify the code so that it can display any requested page stored in the root folder.? how will i do that??
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
In your code:
send_doc(int connfd)
{
FILE *fp;
char output[1000];
int len;
read one line (terminated by \r\n) from the socket with handle connfd. This line is in the format I've descibed above.
Then extract the file name and send file back as you've done with index.html.
E.g. if the line is
GET / HTTP/1.x
this is a special case meaning to send index.html in the root dir.
and:
GET /foo.bar HTTP/1.x
Means to send back file foo.bar in your servers root dir.
But as sunnycoder say. First glance through the RFC doc to get an idea what the HTTP protocol demands.
send_doc(int connfd)
{
FILE *fp;
char output[1000];
int len;
read one line (terminated by \r\n) from the socket with handle connfd. This line is in the format I've descibed above.
Then extract the file name and send file back as you've done with index.html.
E.g. if the line is
GET / HTTP/1.x
this is a special case meaning to send index.html in the root dir.
and:
GET /foo.bar HTTP/1.x
Means to send back file foo.bar in your servers root dir.
But as sunnycoder say. First glance through the RFC doc to get an idea what the HTTP protocol demands.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER