Link to home
Start Free TrialLog in
Avatar of pritam123456
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??
ASKER CERTIFIED SOLUTION
Avatar of JugglerW
JugglerW

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of pritam123456
pritam123456

ASKER

i dont really understand what you mean. can you write a sample code for me where should i accept the page name.  give me some more clear information please
SOLUTION
Avatar of sunnycoder
sunnycoder
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial