在之前的博客我们了解HTTP通信的请求与应答的内容,知道了这些之后,我们就可以从原理上简单仿写HTTP服务器了。
在Linux下我们当我们使用HTTP协议进行通讯,即客户端在浏览器请求服务器的某个服务(页面)。我们在主机上进行测试的时候,可以开启httpd服务以处理客户端的请求,一般来说我们的页面放在/var/www/html底下,我们这些操作需要切换到root用户。
在设置HTTP的相关信息时,我们需要用到以下几个命令:
- 开启httpd服务 : service httpd start
- 查看httpd状态 : service httpd status
- 关闭httpd服务 : service httpd stop
首先我们来查看一下我自己http的状态:
我们可以看到我的http目前处于未开启状态,接下来我们先开启http服务,
在请求页面之前献给大家看一下我在/var/www/html底下写的一个页面:
然后我们来请求这个页面:
可以看到我们成功的请求到了这个页面。那么这个到底是怎么实现的的呢,我们来看下面:
在执行我们自己的代码前,我们要先关闭http服务,否则,root会占用80端口,导致我们无法绑定,出现下面的状况:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/stat.h>
#include<fcntl.h>
void SendError(int c)
{
char buff[1024]={0};
strcpy(buff,"HTTP/1.1 404 NOT FOUND\n\r");
strcat(buff,"Server:myhttp/1.0\n\r");
strcat(buff,"Content-Length: ");
sprintf(buff+strlen(buff),"%d",0);
strcat(buff,"\n\r");
strcat(buff,"Content-Type:text/html;charset=utf-8\n\r");
strcat(buff,"\n\r");
strcat(buff,"404 NOT FOUND");
send(c,buff,strlen(buff),0);
}
void SendHead(int size,int c)
{
char buff[1024]={0};
strcpy(buff,"HTTP/1.1 200 OK\n\r");
strcat(buff,"Server:myhttp/1.0\n\r");
strcat(buff,"Content-Length: ");
sprintf(buff+strlen(buff),"%d",size);
strcat(buff," \n\r");
strcat(buff,"Content-Type:text/html;charset=utf-8\n\r");
strcat(buff,"\n\r");
send(c,buff,strlen(buff),0);
}
void AnayRequest(char *buff,char *pathname)
{
char *p=strtok(buff," ");
p=strtok(NULL," ");
strcpy(pathname,"/var/www/html");
strcat(pathname,p);
}
void SendData(char *pathname,int c)
{
struct stat st;
if(-1!=stat(pathname,&st))
{
SendHead(st.st_size,c);
}
else
{
SendError(c); //
return;
}
int fd=open(pathname,O_RDONLY);
if(fd==-1)
{
SendError(c);
return;
}
while(1)
{
char buff[128]={0};
int n=read(fd,buff,127);
if(n<=0)
{
close(fd);
break;
}
send(c,buff,strlen(buff),0);
}
}
int main()
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in ser,cli;
ser.sin_family=AF_INET;
ser.sin_port=htons(80);
ser.sin_addr.s_addr=inet_addr("127.0.0.1");
int res=bind(sockfd,(struct sockaddr *)&ser,sizeof(ser));
if(res==-1)
{
printf("bind fail!");
exit(0);
}
listen(sockfd,5);
while(1)
{
int len=sizeof(cli);
int c=accept(sockfd,(struct sockaddr*)&cli,&len);
if(c<0)
continue;
char buff[1024]={0};
int n=recv(c,buff,1023,0);
if(n<=0)
{
close(c);
continue;
}
printf("%s\n",buff);
char pathname[128]={0};
AnayRequest(buff,pathname);
SendData(pathname,c);
close(c);
}
}