HTTP的简单仿写

        在之前的博客我们了解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);
	}
}

猜你喜欢

转载自blog.csdn.net/pretysunshine/article/details/84885313
今日推荐