Simple HTTP Server
Prerequisites : Socket and thread programming
HTTP is a protocol used for communication between a browser and a web server.
How HTTP works : When you type in a URL in the browser and click GO the browser extracts the host-name section and uses DNS to obtain the IP address of the web server that host the web site. The browser then uses this IP address to form a TCP connection to the web server. The browser sends HTTP request to retrieve a specific page. If the page exist the server responds by sending the copy of the page in the HTTP response (response code - 400). If the file doesn't exists in the server, the server send HTTP response containing a response code 404 (Not Found Error Message).
HTTP Request
The request message syntax:
- Request line, for eg : GET /images/logo.png HTTP/1.1
- Headers
- An empty line.
- An optional message body.
GET / HTTP/1.1
Host: 127.0.0.1:2003
Explanation:
Line 1 : "GET" indicates the request method used . Other methods are PUT, POST etc
"/" indicates the requested page, here its the root page i.e index.html
"HTTP/1.1" version of HTTP used
Line 2 : "HOST" host to which request is send
"127.0.0.1" IP address of host
"2003" is the port used
More about HTTP request and headers can be found at
http://en.wikipedia.org/wiki/HTTP_request
HTTP Response
The response message consists of the following:
- A Status-Line
- Headers
- An empty line
- An optional message body
HTTP/1.1 200 OK
Content-type: text/html
<html>
<head></head>
<body>
<h1>Header</h1>
<p>Congrats !! your HTTP server is working.</p>
</body>
</html>
Explanation :
Line 1 : "HTTP/1.1" HTTP version used
"200" status code
"OK" description of status code
Line 2 : "Content-type: text/html" indicates type of the file.
Line 3 : HTML code of the page
More about HTTP response and headers
http://en.wikipedia.org/wiki/HTTP_response
HTTP status code
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
/*------------------------------Simple HTTP Server----------------------------*/
#include<sys/socket.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include <netdb.h>
#define BUFF_LEN 1028
pthread_t c;
/* HTTP response and header for a successful request. */
static char* ok_response =
"HTTP/1.1 200 OK\n"
"Content-type: text/html\n"
"\n"
"<html>\n"
"<head></head>\n"
" <body>\n"
" <h1>Header</h1>\n"
" <p>Congrats !! your HTTP server is working.</p>\n"
" </body>\n"
"</html>\n";
void * serve_client(int tsd)
{
int k;
char buff[BUFF_LEN]; //used to store the HTTP request
printf("[Server : %d].\n",tsd);
k=recv(tsd,buff,BUFF_LEN,0);
if(k==-1)
printf("[Server : %d] recv() failed.\n",tsd);
else printf("[Server : %d] recv() OK .\n",tsd);
// Printing the HTTP request recieved
printf("[Server : %d] Recieved : %s\n",tsd,buff);
/* Actual HTTP server does some processing and responds accordingly.
* Here I have just send a HTTP response.
*/
//Sending the HTTP response
write (tsd, ok_response, strlen (ok_response));
close(tsd);
printf("[Server : %d] going to pthread_exit().\n\n",tsd);
pthread_exit(NULL);
}
int main(int argc,char *argv[])
{ char buff[100];
int k;
socklen_t len;
int sock_desc,temp_sock_desc;
short port;
struct sockaddr_in server,client;
printf("[Server] Start . Next memset()\n");
memset(&server,0,sizeof(server));
memset(&client,0,sizeof(client));
printf("[Server] memset() OK . Next socket()\n");
sock_desc=socket(AF_INET,SOCK_STREAM,0);
printf("[Server] socket() OK . Next bind()\n");
server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
port = (argc > 1) ? atoi(argv[1]) : 3001; //default port : 3001
server.sin_port=htons(port);
k=bind(sock_desc,(struct sockaddr*)&server,sizeof(server));
if(k==-1)
printf("[Server] bind() failed.\n");
else printf("[Server] bind() OK . Next listen()\n");
k=listen(sock_desc,10);
if(k==-1)
printf("[Server] listen() failed.\n");
else printf("[Server] listen() OK . Next accept()\n");
len=sizeof(client);
while(1)
{
temp_sock_desc=accept(sock_desc,(struct sockaddr*)&client,&len);
printf("\n[Server] accept() OK .\n");
printf("[Server] Client IP : %s.\n",(char*)inet_ntoa(client.sin_addr));
printf("[Server] sock_desc : %d.\n",sock_desc);
printf("[Server] temp_sock_desc : %d.\n",temp_sock_desc);
/*
* Start a thread to server each client.
*/
pthread_create( &c,NULL,(void *)serve_client, (int *) temp_sock_desc);
}
close(temp_sock_desc);
close(sock_desc);
exit(0);
return 0;
}
/*------------------------------End Of Program----------------------------*/
Working :
This programs waits for a client to connect and then starts a thread to serve the client.
This thread recieves a message(HTTP request) from the client and sends a HTTP response
to the client.
A real HTTP server does more than this. It includes
- checking if the requested file exist and send response accordingly.
- Integration of Server side scripting languages like PHP,ASP,JSP.etc
- status code based actions
- caching
- and so on
By parsing through the HTTP request the requirements of the client can be understood and
required output can be generated.
Compiling and running :
- Copy the code and paste it in a file,say "server.c"
- compile : gcc server.c -lpthread
- run : ./a.out 2001
- In browser : http://127.0.0.1:2001/