C语言编写的HTTP服务器源码分享 (http服务器c 源码)
随着互联网的不断发展,Web应用已经成为人们生活和工作中不可或缺的一部分。而Web应用的背后则是HTTP服务器。HTTP服务器充当着Web应用与客户端之间的一个桥梁,主要用于处理客户端的请求,并向其返回Web应用所需的资源。因此,HTTP服务器的性能和安全性至关重要。本文将分享一个用C语言编写的HTTP服务器源码,读者可以通过学习该代码掌握HTTP服务器的基本实现原理。
一、HTTP协议简介
HTTP(Hypertext Transfer Protocol)协议是一种基于TCP/IP协议通信的应用级协议,最初用于在全球范围内的万维网(World Wide Web)中传输超文本(hypertext),随着Web应用的发展,HTTP协议已经越来越广泛地应用于信息传输。HTTP协议定义了客户端如何请求资源,以及服务器如何响应这些请求。HTTP请求和响应用于描述客户端和服务器之间的通信,并包含HTTP头和消息正文。
二、HTTP服务器实现原理
HTTP服务器主要分为两个部分:监听客户端请求和响应客户端请求。当客户端请求连接时,服务器会建立一个TCP/IP连接。这样,服务器就能监听并处理客户端的请求。一般来说,HTTP服务器需要处理GET请求和POST请求。
几乎所有HTTP请求都遵循相同的一般过程:客户端发送HTTP请求,服务器接收HTTP请求并分析它,服务器向客户端发送HTTP响应,并断开TCP连接。
GET请求:当客户端用HTTP发送GET请求时,服务器将解析并响应请求。GET请求本身不会更改服务器上的任何内容,只将请求参数附加到URL中。服务器在响应GET请求时返回所请求的数据。
POST请求:当客户端用HTTP发送POST请求时,服务器将解析并响应请求。POST请求可能更改服务器上的资源,例如向数据库插入新记录。POST请求的参数通常通过HTTP正文传递。服务器在响应POST请求时返回客户端状态。
三、C语言编写HTTP服务器
下面是一个用C语言编写的HTTP服务器示例代码,主要实现了GET和POST请求的处理。该代码实现了一个基本的HTTP服务器,可以接收客户端请求并返回响应数据。其中,socket编程是实现服务器的关键技术。
“`c
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXSIZE 1024
void error(char *err){
perror(err);
exit(EXIT_FLURE);
}
void recv_line(int sock, char *buf,int len){
int i = 0;
char c = ‘\0’;
int n = -1;
while((i
(c != ‘\n’)){
n = recv(sock,&c,1,0);
if(n > 0){
if(c == ‘\r’){
n = recv(sock,&c,1,MSG_PEEK);
if((n > 0)&&(c == ‘\n’))
recv(sock,&c,1,0);
else
c = ‘\n’;
}
buf[i] = c;
i++;
}
else
c = ‘\n’;
}
buf[i] = ‘\0’;
}
int get_line(int sock,char *buf,int len){
char c=’\0′;
int n;
int i = 0;
while((i
n = recv(sock,&c,1,0);
if(n > 0){
if(c == ‘\r’){
n = recv(sock,&c,1,MSG_PEEK);
if((n > 0)&&(c == ‘\n’))
recv(sock,&c,1,0);
else
c = ‘\n’;
}
buf[i] = c;
i++;
}
}
buf[i] = ‘\0’;
return i;
}
void process_conn(int sc){
char buf[MAXSIZE];
int numchars;
char method[255];
char url[255];
char path[512];
char *query_string=NULL;
recv_line(sc,buf,sizeof(buf));
numchars = get_line(sc,buf,sizeof(buf));
int i=0,j=0;
while(!isspace(buf[j])&&(i
method[i] = buf[j];
i++,j++;
}
method[i] = ‘\0’;
if(strcasecmp(method,”GET”)&&strcasecmp(method,”POST”)){
printf(“error http request\n”);
exit(EXIT_FLURE);
}
i=0;
while(isspace(buf[j])&&j
j++;
}
while(!isspace(buf[j])&&i
url[i] = buf[j];
i++,j++;
}
url[i]=’\0′;
if(strcasecmp(method,”GET”) == 0){
query_string = url;
while((*query_string != ‘?’)&&(*query_string != ‘\0’)){
query_string++;
}
if(*query_string == ‘?’){
*query_string = ‘\0’;
query_string++;
}
}
sprintf(path,”htdocs%s”,url);
if(path[strlen(path)-1] == ‘/’){
strcat(path,”index.html”);
}
struct stat st;
if(stat(path,&st) == -1){
while(numchars > 0&&strcmp(“\n”,buf)){
numchars = get_line(sc,buf,sizeof(buf));
}
printf(“error http 404—-\n”);
exit(EXIT_FLURE);
}
else{
int fd = open(path,O_RDON);
char ret[1024];
sprintf(ret,”HTTP/1.0 200 OK\r\n”);
send(sc, ret, strlen(ret),0);
sprintf(ret,”Content-Length: %ld\r\n”,st.st_size);
send(sc, ret, strlen(ret),0);
sprintf(ret,”\r\n”);
send(sc, ret, strlen(ret),0);
sendfile(sc,fd,NULL,st.st_size);
close(fd);
}
close(sc);
}
int mn()
{
int sockfd ,newfd;
socklen_t len;
struct sockaddr_in srvAddr,cliAddr;
int i;
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1)
error(“create socket error”);
memset(&srvAddr,0,sizeof(struct sockaddr));
srvAddr.sin_family = AF_INET;
srvAddr.sin_port = htons(80);
srvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockfd,(struct sockaddr*)&srvAddr,sizeof(srvAddr))
error(“bind error”);
if(listen(sockfd,10)
error(“listen error”);
char buf[MAXSIZE];
while(1){
memset(buf,0,MAXSIZE);
len = sizeof(cliAddr);
newfd = accept(sockfd,(struct sockaddr*)&cliAddr,&len);
if(newfd
error(“accept error”);
}
process_conn(newfd);
}
close(sockfd);
return 0;
}
“`
四、HTTP服务器测试
我们可以用浏览器发送HTTP请求测试该代码。例如,在命令行中输入以下命令,可以在Chrome浏览器中打开60.205.218.253。
“`shell
firefox http://60.205.218.253/
“`
在浏览器地址栏输入上述命令后,可以看到服务器向浏览器返回了一个包含HTML代码的页面。
五、