// have 4 file descriptors to experiment with the select function call
// if web request's file descriptor (a socket) is reading, write back to it after forking
// if keyboard gives a read request, write to screen with it.
// this will be the first web server on the planet to read from both the keyboard and the web!!
// TODO: figure out how to make this thing stop. Doesn't respond to ctrl-c or ctrl-d i can only suspend it.
// with the code from web_server.c from http://www.iro.umontreal.ca/~cotema/ift6815/web_server.c
// Copyright (C) 2003 by Martin Cote
#include <termios.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_SIZE 1024
int debug = 0;
void dump_fds(char *name, fd_set *set, int max_fd)
{
int i;
if(!debug) return;
fprintf(stderr, "%s:", name);
for(i=0; i<max_fd; i++) {
if(FD_ISSET(i, set)) {
fprintf(stderr, "%d,", i);
}
}
fprintf(stderr, "\n");
}
int main(int argc, char ** argv)
{
char buf[BUF_SIZE+1];
int sock0;
int http_fd;
struct sockaddr client;
struct sockaddr_in addr;
sock0 = socket(PF_INET, SOCK_STREAM, 0);
int port;
int keyboard;
int screen;
// char c;
int rc;
// struct termios tio;
fd_set readfds;
fd_set writefds;
// fd_set exceptfds;
struct timeval tv;
int max_fd;
/* inbound and outbound keep track of whether we have a character */
/* already read which needs to be sent in that direction */
/* the _char variables are the data buffer */
int outbound;
char outbound_char;
int inbound;
char inbound_char;
if (argc != 2)
{
printf("Utilisation: ./select_test <port>");
return 0;
}
port = atoi(argv[1]);
/* set up the 2 local file descriptors */
keyboard = open("/dev/tty",O_RDONLY| O_NONBLOCK);
assert(keyboard>=0);
screen = open("/dev/tty",O_WRONLY| O_NONBLOCK);
assert(screen>=0);
assert(sock0)>=0);
/* set up web file descriptor */
addr.sin_family = PF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(debug) {
fprintf(stderr, "keyboard=%d\n",keyboard);
fprintf(stderr, "screen=%d\n",screen);
fprintf(stderr, "http_fd=%d\n",http_fd);
}
FD_ZERO(&writefds);
FD_ZERO(&readfds);
max_fd = 0;
if(screen > max_fd) max_fd=screen;
if(keyboard > max_fd) max_fd=keyboard;
if(http_fd > max_fd) max_fd=http_fd;
max_fd++; // first arg to select has max fd +1
if(debug) fprintf(stderr, "max_fd=%d\n",max_fd);
tv.tv_sec = 10; // sleep(10);
tv.tv_usec = 0;
dump_fds("read in", &readfds, max_fd);
dump_fds("write in", &writefds, max_fd);
rc= select(max_fd, &readfds, &writefds, NULL, &tv);
if(rc==0) continue; /* timeout */
dump_fds("read out", &readfds, max_fd);
dump_fds("write out", &writefds, max_fd);
if(FD_ISSET(keyboard, &readfds)) {
rc=read(keyboard,&outbound_char,1);
if(debug) fprintf(stderr, "\nreading outbound=%d\n",outbound_char);
if(rc==1) outbound=1;
if(outbound == 3) exit(0);
}
if(FD_ISSET(http_fd, &readfds)) {
rc=read(http_fd,&inbound_char,1);
if(debug) fprintf(stderr, "\nreading inbound=%d\n",inbound_char);
if(rc==1) outbound=1;
}
if(FD_ISSET(screen, &writefds)) {
if(debug) fprintf(stderr, "\nwriting inbound\n");
rc=write(screen,&inbound_char,1);
if(rc==1) outbound=1;
}
if(FD_ISSET(sock0, &writefds)) {
if(debug) fprintf(stderr, "\nwriting outbound\n");
// printf("Accepting connections on port %d\n", port);
bind(sock0, (struct sockaddr*)&addr, sizeof(addr));
listen(sock0, 5);
int client_len = sizeof(client);
http_fd = accept(sock0, &client, &client_len);
if (fork() == 0) // fork child and handle request in the chile
{
close(sock0);
read(http_fd, buf, BUF_SIZE);
char * header = "Content-type=text/html\n\n<html><title>IFT6815</title><body><h1>IFT6815 web server</h1><h3><a href=\"http://www.sirfsup.com/languages/c/unix_c/select/web_server.c\">I put it here</a></h3></body></html>";
char c = 'z';
write(http_fd, header, strlen(header));
write(http_fd, z, 1);
char * screen_out = "Ecriture?\n";
write(screen, screen_out, strlen(screen_out));
}
wait();
}
close(http_fd);
exit(0);
}
return to top