Keywords

.NET (3) .rb (1) *.cod (1) 3110c (1) Algorithm (1) Amazon Cloud Drive (1) amkette (1) Android (1) Apex (6) apex:dynamic (1) API (1) API version (1) Application Development Contest (2) Artificial Intelligence (2) Atricore (1) b2g (1) Binary Search Tree (1) Blackberry Application Development (1) Blackberry Java Development Environment (1) Blender Game Engine (1) bluetooth (2) Boot2Gecko (1) bug fix (1) C (1) C++ (2) Cloud computing (1) Cloud Storage (1) Code Blocks (1) Code for a Cause (2) codejam (1) Coding (1) const_cast (1) Custom Help (1) Dancing With the Googlers (1) Data Structures (1) desktop environment (5) Doubly Linked List (1) Dropbox (1) dynamic visualforce component (1) dynamic_cast (1) Enterprise WSDL (1) Execution Context (1) fedora 14 (1) fedora 17 (5) Firefox OS (1) Flashing Nokia 3110c handset (1) Force.com (7) Gaia (1) Game Developement (1) GCC (2) GDG (2) Goank (1) Google (4) Google Developer Group (2) Google Drive (1) GTK+ (5) HACK2012 (2) Hall of Mirrors (1) help for this page (1) HTML5 (2) HTTP Web Server (1) IDE (1) Identity Provider (1) install (1) Intelligent Systems (1) Java (1) JDE (1) JOSSO (1) location based social network (1) machine learning (1) me.social (1) MinGW (1) Natural Language Processing (1) Natural Language Toolkit (1) neckphone (1) NLKT (1) Nokia Pheonix (1) Notebook (1) Numeric XML Tags (1) OAuth2.0 (1) OLPC (7) OLPC-XO-1 (7) One Laptop per Child (5) Override custom help (1) Paas (1) Partner WSDL (1) Polymorphism (1) programming contest (1) PyGTK (4) Python (11) Recycled Numbers (1) reinterpret_cast (1) Research (1) REST (1) RM-237 (1) Robotics (1) Ruby (1) Saas (2) Salesforce.com (7) scikit-learn (1) SDK (1) Service Provider (1) Single sign on (1) sklearn (1) SOAP (3) Speaking in Tongues (1) SSO Agent (1) SSO Gateway (1) static_const (1) sugar (7) sugar activity (4) sugarlabs (7) SVG (2) Symbiotic AI (1) Tabbed container (1) TCP/IP (1) TCP/IP stack (1) Typecasting (1) typeid (1) ubuntu 13.10 (1) UDP (1) Upgrade Assembly (1) Visualforce (2) Web Server (1) Web Services (3) Web2.0 (1) wikipedia (1) wikipediaHI (1) WSDL (1) XML tags (1)

Thursday, July 12, 2012

Simple HTTP Web server in C Language


Hi Guys !


This post helps you to write your own simple HTTP Web server in C language. This will give you a direction on how to proceed with writing web server using Berkeley Sockets( part of Berkeley Software Distribution). Berkeley sockets (or BSD sockets) is a computing library with an application programming interface (API) for internet sockets and Unix domain sockets, used for inter-process communication (IPC). We will get in details of socket in further section.

Lets discuss about traditional client-server architecture. Server is a process/layer which is listening on a port for requests to serve resources. Client is a process/layer which is requesting for the service or resource hosted on the server.

Server listens on a specific port for requests and respond to request on same connection. A socket is basically combination of IP and port number i.e. [IP,port number] defines a socket. As per TCP/IP software stack we can have TCP connection as well as UDP connections. Each have specific purpose. TCP is a connection oriented protocol and UDP is not connection oriented.i.e it send packets independent of each other. UDP does not guarantee delivery of packets.


Lets consider the flow of socket communication between client and server : The diagram shown below describes sequence of function call made to establish socket connection and exchange data.
 Server:
1. Invoke socket() function to get socket identifier. set options for socket if required using setsockopt()
2. Invoke bind() function to bind server to a specific IP and port number.
3. Invoke listen() function to make server listen on port for incoming requests.
4. Invoke accept() function whenever incoming request is received.
5. Exchange data using send() and recv() functions.
6. Terminate the socket connection using close() function.

Client:
1. Invoke socket() function to get socket identifier. set options for socket if required using setsockopt().
2. Invoke connect() function to connect to a server listening for requests at specific IP and port.
3. Once connection is established, exchange data using send() and recv() functions.
4. Terminate the socket connection using close() function.

I have shared the code for HTTP server written in C Language which returns HTML data on GET request at 8080 port:


/*
/*
Simple HTTP Web Server 
By : Kartik Kumar Perisetla(kartik.peri@gmail.com)
hosted for http://kperisetla.blogspot.com
*/

//for windows 
#include<winsock2.h>

// for POSIX based systems use- #include<sock.h> in place of #include<winsock2.h>

#include<sys/types.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#pragma comment(lib, "Ws2_32.lib")


//function specific for Windows-to be called before invoking call to socket()
int init()
{
 WSADATA wsaData;
 int iResult;

 // Initialize Winsock
 iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
 if (iResult != 0) 
 {
  printf("WSAStartup failed: %d\n", iResult);
  return 1;
 }

}

//function specific for windows-to be called after all socket communication is complete
void clean()
{
 WSACleanup();
}
int main()
{


 while(1)
 {
  init();
  server();
  clean();
 }
  
    return 0;
} 

void server()
{
 
        int sock, connected, bytes_recieved , true = 1;  
        char send_data [1024] , recv_data[1024];       

        struct sockaddr_in server_addr,client_addr;    
        int sin_size;
        
        if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            perror("Socket");
            exit(1);
        }

        if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) {
            perror("Setsockopt");
            exit(1);
        }
        
        server_addr.sin_family = AF_INET;         
        server_addr.sin_port = htons(8080);     
        server_addr.sin_addr.s_addr = INADDR_ANY; 
        //bzero(&(server_addr.sin_zero),8); --This is for POSIX based systems
  memset(&(server_addr.sin_zero),0,8);
        if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1) 
    {
            perror("Unable to bind");
            exit(1);
        }

        if (listen(sock, 5) == -1) 
  {
            perror("Listen");
            exit(1);
        }
  
  printf("\n\nMyHTTPServer waiting on port 8080");
        fflush(stdout);
        

            sin_size = sizeof(struct sockaddr_in);

            connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);

           // printf("\n I got a connection from (%s , %d)",
                //   inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));

   char kk[9999];
   recv(connected,kk,sizeof(kk),0);
   printf("\n Received:%s",kk); 
   
   char xx[9999];
   strcpy(xx,"HTTP/1.1 200 OK\nContent-length: 47\nContent-Type: text/html\n\n<html><body><H1>Hello Kartik</H1></body></html>");
   
   int c=send(connected,&xx,sizeof(xx),0);
   printf("\nSTATUS:%d",c);
     
   printf("\nSent : %s\n",xx);
   
            close(sock);
   WSACleanup();
}


After writing this code, compile it and run it. I compiled this code using GCC compiler version 4.5.2.
GCC comes within Linux OS. For windows systems you can download minGW which consists of gcc, g++,etc.


Once you start the server by double clicking server.exe file you will see like this:

Now open up browser and navigate to URL : http://127.0.0.1:8080 and see the server responding to your request with web page. i.e HTML data:
and in the server console you can see the request structure and response returned:

I hope this post helps you in understanding the concept of socket communication and writing a simple HTTP web server in C language. 

Cheers !



7 comments:

rahul singh said...

Finally its on the blog...Waiting for Hemant's review :P

Kartik Kumar said...

hahaha... ;) Hemant will not give any comment on this !

NANDA KISHORE said...

Good work Kartik.
Really nice to have the basic understanding of web server.

Zahid Rahman said...
This comment has been removed by a blog administrator.
Batuhan Göksu said...

hi

On unix-based Mac OS X that you have been receiving this error, how can I solve the code to compile with gcc

Last login: Wed Aug 14 22:34:30 on ttys000
desertsun:~ desertsun$ gcc /Users/desertsun/Desktop/httpd.c -o
llvm-gcc-4.2: argument to '-o' is missing
desertsun:~ desertsun$ gcc /Users/desertsun/Desktop/httpd.c -o test
/Users/desertsun/Desktop/httpd.c: In function ‘init’:
/Users/desertsun/Desktop/httpd.c:25: error: ‘WSADATA’ undeclared (first use in this function)
/Users/desertsun/Desktop/httpd.c:25: error: (Each undeclared identifier is reported only once
/Users/desertsun/Desktop/httpd.c:25: error: for each function it appears in.)
/Users/desertsun/Desktop/httpd.c:25: error: expected ‘;’ before ‘wsaData’
/Users/desertsun/Desktop/httpd.c:29: error: ‘wsaData’ undeclared (first use in this function)
/Users/desertsun/Desktop/httpd.c: At top level:
/Users/desertsun/Desktop/httpd.c:58: warning: conflicting types for ‘server’
/Users/desertsun/Desktop/httpd.c:50: warning: previous implicit declaration of ‘server’ was here
/Users/desertsun/Desktop/httpd.c: In function ‘server’:
/Users/desertsun/Desktop/httpd.c:63: error: storage size of ‘server_addr’ isn’t known
/Users/desertsun/Desktop/httpd.c:63: error: storage size of ‘client_addr’ isn’t known
/Users/desertsun/Desktop/httpd.c:66: error: ‘AF_INET’ undeclared (first use in this function)
/Users/desertsun/Desktop/httpd.c:66: error: ‘SOCK_STREAM’ undeclared (first use in this function)
/Users/desertsun/Desktop/httpd.c:71: error: ‘SOL_SOCKET’ undeclared (first use in this function)
/Users/desertsun/Desktop/httpd.c:71: error: ‘SO_REUSEADDR’ undeclared (first use in this function)
/Users/desertsun/Desktop/httpd.c:78: error: ‘INADDR_ANY’ undeclared (first use in this function)
/Users/desertsun/Desktop/httpd.c:81: error: invalid application of ‘sizeof’ to incomplete type ‘struct sockaddr’
/Users/desertsun/Desktop/httpd.c:97: error: invalid application of ‘sizeof’ to incomplete type ‘struct sockaddr_in’
desertsun:~ desertsun$
desertsun:~ desertsun$

Kartik Kumar Perisetla said...

Hi Batuhan Göksu,

For windows framework(.net or COM) you will use WSADATA. For POSIX based systems, you need to use their specific data structures.

SHIVA SURYA said...

Really awesome post sir!