I believe you have heard about Apache, which is the most widely used web server in China. You can learn from news.netcraft.com/ The site was confirmed.
This is Tencent’s uptime.netcraft.com/up/graph?site=www . qq.com.Apache The mode of powerful function, efficient performance and open source code is very attractive to me, but the rogue’s own level is limited, so he can’t get a clear idea from Apache’s huge source code. So, I came up with the idea of writing a small and simple web server by myself, hoping to help my friends who are also interested in this aspect.

My experimental environment is as follows
OS:Red Hat Enterprise Linux 5
gcc:4.1.2
libc:2.5
editor:Vim
lang:C
Reading the source code requires the following preparatory knowledge:
Fundamentals of C language
Fundamentals of Linux Programming
Socket programming foundation (Linux)
Basic principles of TCP / IP
HTTP Fundamentals
Key words:
Linux C, Web HTTP Server, Linux Socket.
———————————————————————————–
The following is the first version of Mutu (0.1 alpha), which implements the most basic functions of the web server
Includes the following source files:
Webserver. C — program entry
init_ socket.h init_ Socket. C — completes the initialization of some web servers
get_ time.h get_ Time. C — time to get the server
http_ session.h http_ Session. C — process an HTTP session
The following is the source code of each file:
webserver.c:

/*
* file:webserver.c
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include”get_time.h”
#include”init_socket.h”
#include”http_session.h”
intmain(intargc,char*argv[])
{
intlisten_fd;
intconnect_fd;
structsockaddr_inserver_addr;
structsockaddr_inclient_addr;
bzero(&server_addr,sizeof(structsockaddr_in));
bzero(&client_addr,sizeof(structsockaddr_in));
if(init_socket(&listen_fd,&server_addr)==-1)
{
perror(“init_socket() error. in webserver.c”);
exit(EXIT_FAILURE);
}
socklen_taddrlen=sizeof(structsockaddr_in);
pid_tpid;
while(1)
{
if((connect_fd=accept(listen_fd,(structsockaddr*)&client_addr,&addrlen))==-1)
{
perror(“accept() error. in webserver.c”);
continue;
}
if((pid=fork())>0)
{
close(connect_fd);
continue;
}
elseif(pid==0)
{
close(listen_fd);
printf(“pid %d process http session from %s : %d\n”,getpid(),inet_ntoa(client_addr.sin_addr),htons(client_addr.sin_port));
if(http_session(&connect_fd,&client_addr)==-1)
{
perror(“http_session() error. in webserver.c”);
shutdown(connect_fd,SHUT_RDWR);
printf(“pid %d loss connection to %s\n”,getpid(),inet_ntoa(client_addr.sin_addr));
exit(EXIT_FAILURE);/* exit from child process, stop this http session */
}
printf(“pid %d close connection to %s\n”,getpid(),inet_ntoa(client_addr.sin_addr));
shutdown(connect_fd,SHUT_RDWR);
exit(EXIT_SUCCESS);
}
else
{
perror(“fork() error. in webserver.c”);
exit(EXIT_FAILURE);
}
}
shutdown(listen_fd,SHUT_RDWR);
return0;
}
init_socket.h
/*
* file:init_socket.h
*/
#ifndefINIT_SOCKET_H
#defineINIT_SOCKET_H
#include
#defineBACKLOG 20/* length of listening queue on socket */
#definePORT 8080/* web server listening port */
/* initialize the socket on server, include below
socket();
bind();
listen();
*/
/* listen_fd : the web server listen file decriptor
server_addr: the web server ipv4 address
RETURNS: success on 0, error on -1
*/
intinit_socket(int*listen_fd,structsockaddr_in*server_addr);
#endif
init_socket.c
/*
* file:init_socket.c
*/
#include
#include
#include
#include
#include
#include
#include”init_socket.h”
intinit_socket(int*listen_fd,structsockaddr_in*server_addr)
{
if((*listen_fd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror(“socket() error. in init_socket.c”);
return-1;
}
/* set reuse the port on server machine */
intopt=SO_REUSEADDR;
if(setsockopt(*listen_fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))==-1)
{
perror(“setsockopt() error. in init_socket.c”);
return-1;
}
server_addr->sin_family=AF_INET;
server_addr->sin_port=htons(PORT);
server_addr->sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(*listen_fd,(structsockaddr*)server_addr,sizeof(structsockaddr_in))==-1)
{
perror(“bind() error. in init_socket.c”);
return-1;
}
if(listen(*listen_fd,BACKLOG)==-1)
{
perror(“listen() error. in init_socket.c”);
return-1;
}
return0;
}
get_time.h
/*
* file: get_time.h
*/
#ifndefGET_TIME_H
#defineGET_TIME_H
#defineTIME_BUFFER_SIZE 40/* buffer size of time_buffer */
char*get_time_str(char*time_buf);
#endif
get_time.c
/*
* file:get_time.c
*/
#include
#include
#include
#include”get_time.h”
/* get the time on server,
return: the ascii string of time , NULL on error
argument: time_buf the buffer to store time_string
*/
char*get_time_str(char*time_buf)
{
time_tnow_sec;
structtm*time_now;
if(time(&now_sec)==-1)
{
perror(“time() in get_time.c”);
returnNULL;
}
if((time_now=gmtime(&now_sec))==NULL)
{
perror(“localtime in get_time.c”);
returnNULL;
}
char*str_ptr=NULL;
if((str_ptr=asctime(time_now))==NULL)
{
perror(“asctime in get_time.c”);
returnNULL;
}
strcat(time_buf,str_ptr);
returntime_buf;
}
http_session.c
/*
* file: http_session.h
*/
#ifndefHTTP_SESSION_H
#defineHTTP_SESSION_H
#include
#defineRECV_BUFFER_SIZE 1024/* 1KB of receive buffer */
#defineSEND_BUFFER_SIZE 1050000/* 1.xMB of send buffer */
#defineURI_SIZE 128/* length of uri request from client browse */
#defineTIME_OUT_SEC 10/* select timeout of secend */
#defineTIME_OUT_USEC 0/* select timeout of usecend */
#defineFILE_OK 200
#defineFILE_FORBIDEN 403/* there are no access permission*/
#defineFILE_NOT_FOUND 404/* file not found on server */
#defineUNALLOW_METHOD 405/* un allow http request method*/
#defineFILE_TOO_LARGE 413/* file is too large */
#defineURI_TOO_LONG 414/* */
#defineUNSUPPORT_MIME_TYPE 415
#defineUNSUPPORT_HTTP_VERSION 505
#defineFILE_MAX_SIZE 1048576/* 1MB the max siee of file read from hard disk */
#defineALLOW”Allow:GET”/* the server allow GET request method*/
#defineSERVER”Server:Mutu(0.1 Alpha)/Linux”
/* if the connect protocol is http then this function deal with it */
inthttp_session(int*connect_fd,structsockaddr_in*client_addr);
/* if http protocol return 1, else return 0 */
intis_http_protocol(char*msg_from_client);
/* get the request header’s uri */
char*get_uri(char*req_header,char*uri_buf);
/* get the uri status,access return 0, not exist return 1, permission deny return 2, error return -1 */
intget_uri_status(char*uri);
/* get the mime type of the file request in uri from client’s browse */
char*get_mime_type(char*uri);
/* read the file which requested by client in uri ,and store in entity_buf.
success return bytes readed,error return -1
*/
intget_file_disk(char*uri,unsignedchar*entity_buf);
/* set http replay header’s status:
200:ok
404:file not found
*/
intset_rep_status();
intset_error_information(unsignedchar*send_buf,interrorno);
intreply_normal_information(unsignedchar*send_buf,unsignedchar*file_buf,intfile_size,char*mime_type);
#endif
How to access the server?
First of all, you need to know the IP address of the running server host. Enter the following command on the server host (super user permissions are required)
ifconfig

If you are using Ethernet, you will see this line
inet addr:xxx.xxx.xxx broadcast:xxx.xxx.xxx.xxx mask:255.xxx.xxx.xxx
XXX stands for the number (000-255). The number after the first INET addr is your network card address.
If you are testing on this machine, you can directly use 127.0.0.1 (loopback address, localhost) as the IP address
After obtaining the IP address of the server, you can access the content of the web server with your favorite browser.
Method: in the address bar of the browser, enter:
http://xxx.xxx.xxx.xxx:8080
Just press enter( xxx.xxx.xxx . XXX has no server IP address just obtained, and 8080 is the preset port).
Click to learn more information, more free open source projects and courses for you to watch!