Today we discuss simple web server program. It accepts only one connection from a web client. Reads the HTTP messages from the client. Sends the HTTP message to the client.
Listening to the HTTP Port
Line 13 - Create a TCP Socket Stream
Line 23 - Fill in the details of IP Address on which server has to run and also port number
Line 27 - Bind the socket and the structure (Observe that 2nd argument is typecasted as 'struct sockaddr *' for the pointer of 'struct sockaddr_in')
Line 34 - Start listening for connections
Accepting the client
Line 43 - Accept the connection. (Observe that 2nd argument is type casted as 'struct sockaddr *' for the pointer of 'struct sockaddr_in'. Also the 3rd argument is pointer to the integer of size, not integer)
Line 43 - Return value of Accept function is client socket ID. This is the ID that we use for reading and writing from that particular client.
Line 53 - Extract IP Address and Port number from the struct sockaddr cliaddr.
Structure of sockaddr_in will be like
Read Client Message
When a browser is opened with the IP Address of machine, it sends out HTTP Get message.
Line 64 - While loop that displays the incoming message from client in batches of 60 characters
And breaking the loop whenever it seen \r\n at the end of message. We are hoping that \r and \n doesnt come in different batches. The probability of occurrence is less
Write Client Message
Line 89 - Start composing Hello Message along with its IP Address and Client Port number
Line 97 - 'Write' the message.
Close Sockets
Line 99 - Close the client socket and also server socket.
Compiling and Executing
This is the execution of the program. Means at the server end. We use curl command line web client, for simplicity. So, the GET message is very simple.
Web Client View
Use the curl command and the IP address. We can see the Hello Message, IP Address and Port Numbers as well.
Instead of curl, we can issue http://10.123.8.110 from chrome or firefox. The messages will be seen on browser.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
#include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <string.h> #include <errno.h> int main() { int servsockfd,clisockfd; struct sockaddr_in servaddr, cliaddr; // Create a TCP Socket servsockfd=socket(AF_INET,SOCK_STREAM,0); if (servsockfd == -1) { printf("socket creation failed\n"); exit(0); } //Populate IP Address and Port Number servaddr.sin_family=AF_INET; servaddr.sin_addr.s_addr=htonl(INADDR_ANY); servaddr.sin_port=htons(80); //Bind the socket to the Structure sockaddr_in containing IP address and Port number if((bind(servsockfd,(struct sockaddr *)&servaddr, sizeof(servaddr))) != 0) { printf("socket bind failed with %d\n",errno); exit(0); } //Start the server and keep listening for connections if((listen(servsockfd,5)) != 0) { printf("Listen failed\n"); exit(0); } else printf("Waiting for client to connect...\n"); //Accept the client connection int cliaddr_len=sizeof(cliaddr); clisockfd = accept(servsockfd,(struct sockaddr *)&cliaddr, &cliaddr_len);if(clisockfd <0) { printf("server accept failed\n"); exit(0); } else printf("Server accepted client\n"); //Store and display the client IP address and Port details char *client_ipaddr = inet_ntoa(cliaddr.sin_addr); int client_port=ntohs(cliaddr.sin_port); char client_port_ascii[10]; sprintf(client_port_ascii,"%d",client_port); printf("Client IP = %s\nClient Port Number=%d\n",client_ipaddr,client_port); char recvline[60]; int i,readlen,linecounter=1; // Read the characters in batches of 60 while ((readlen=read(clisockfd,recvline,60)) >0) { printf("%d -",linecounter,recvline); //Print the HTTP messages from the client in batches of 60 characters for (i=0; i<readlen; i++) { if (recvline[i] == '\n') { printf("\\n"); } else if (recvline[i] == '\r') { printf("\\r"); } else { printf("%c",recvline[i]); } } linecounter++; printf("\n"); //Break the loop if it sees \r\n at the end of messagae if(recvline[readlen-1] == '\n' && recvline[readlen-2] == '\r') { break; } } //Make a HTTP Message to send to client char msg[80]; strcat(msg,"HTTP/1.1 200 OK\nContent-Type: text/plain\n\nHello world!\n"); strcat(msg,"Your IP Address:"); strcat(msg,client_ipaddr); strcat(msg,"\nYour Port Number:"); strcat(msg,client_port_ascii); //Send the message to client write(clisockfd,msg,strlen(msg)); //Close the connections close(clisockfd); close(servsockfd); } |
Listening to the HTTP Port
Line 13 - Create a TCP Socket Stream
Line 23 - Fill in the details of IP Address on which server has to run and also port number
Line 27 - Bind the socket and the structure (Observe that 2nd argument is typecasted as 'struct sockaddr *' for the pointer of 'struct sockaddr_in')
Line 34 - Start listening for connections
Accepting the client
Line 43 - Accept the connection. (Observe that 2nd argument is type casted as 'struct sockaddr *' for the pointer of 'struct sockaddr_in'. Also the 3rd argument is pointer to the integer of size, not integer)
Line 43 - Return value of Accept function is client socket ID. This is the ID that we use for reading and writing from that particular client.
Line 53 - Extract IP Address and Port number from the struct sockaddr cliaddr.
Structure of sockaddr_in will be like
#include <netinet/in.h> struct sockaddr_in { short sin_family; // e.g. AF_INET unsigned short sin_port; // e.g. htons(3490) struct in_addr sin_addr; // see struct in_addr, below char sin_zero[8]; // zero this if you want to }; struct in_addr { unsigned long s_addr; // load with inet_aton() };
Read Client Message
When a browser is opened with the IP Address of machine, it sends out HTTP Get message.
Line 64 - While loop that displays the incoming message from client in batches of 60 characters
And breaking the loop whenever it seen \r\n at the end of message. We are hoping that \r and \n doesnt come in different batches. The probability of occurrence is less
Write Client Message
Line 89 - Start composing Hello Message along with its IP Address and Client Port number
Line 97 - 'Write' the message.
Close Sockets
Line 99 - Close the client socket and also server socket.
Compiling and Executing
# gcc -o webserver webserver.c # ./webserver Waiting for client to connect... Client IP = 10.230.45.13 Client Port Number=63836 Server accepted client 1 -GET / HTTP/1.1\r\nHost: 10.123.8.110\r\nConnection: keep-alive\r\n
This is the execution of the program. Means at the server end. We use curl command line web client, for simplicity. So, the GET message is very simple.
Web Client View
Use the curl command and the IP address. We can see the Hello Message, IP Address and Port Numbers as well.
# curl http://10.123.8.110/
Hello world!
Your IP Address:10.123.8.231
Your Port Number:50416
Instead of curl, we can issue http://10.123.8.110 from chrome or firefox. The messages will be seen on browser.