C / C + + programming diary: using C language to achieve a simple web server (Linux), full code sharing!

Time:2021-1-11

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!

Recommended Today

Don’t see SqlConnection again after using dapper

1、 Background A few days ago, we saw that the bottom layer of a new project of the company used dapper. We all know that dapper is a very powerful semi-automatic ORM, which helps programmers solve the tedious mapping problem. It’s very comfortable to use, but I still encounter a very unpleasant thing, as shown […]