HTTP的通信过程

http通信过程:

                                       

1、URL自动解析 
       HTTP URL包含了用于查找某个资源的足够信息,基本格式如下:HTTP://host[“:”port][abs_path],其中HTTP表示桶盖HTTP协议来定位网络资源;host表示合法的主机域名或IP地址,port指定一个端口号,缺省80;abs_path指定请求资源的URI;如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出,通常这个工作浏览器自动帮我们完成。 
       例如:输入www.163.com;浏览器会自动转换成:HTTP://www.163.com/ 


2、获取IP,建立TCP连接 
        浏览器地址栏中输入"HTTP://www.xxx.com/"并提交之后,首先它会在DNS本地缓存表中查找,如果有则直接告诉IP地址。如果没有则要求网关DNS进行查找,如此下去,找到对应的IP后,则返回会给浏览器。( DNS域名解析分为迭代式和递归式。迭代式降低了根域的压力。其方法使用的比较多。)
         当获取IP之后,就开始与所请求的Tcp建立三次握手连接,连接建立后,就向服务器发出HTTP请求。 如图:

                                                    

3、客户端浏览器向服务器发出HTTP请求 
        一旦建立了TCP连接,Web浏览器就会向Web服务器发送请求命令,接着以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送了一空白行来通知服务器,它已经结束了该头信息的发送。 

4、Web服务器应答,并向浏览器发送数据 
         客户机向服务器发出请求后,服务器会客户机回送应答, 
         HTTP/1.1 200 OK 
        应答的第一部分是协议的版本号和应答状态码,正如客户端会随同请求发送关于自身的信息一样,服务器也会随同应答向用户发送关于它自己的数据及被请求的文档。 
        Web服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据 

5、Web服务器关闭TCP连接 
        一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码 :Connection:keep-alive 
        TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。

HTTP通信代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/stat.h>

int  SendHead(int c,char* path,int status)
{
	char buff[1024] = "HTTP/1.1"; //版本
	sprintf(buff+strlen(buff),"%d",status);
	switch(status)
	{
		case 200:
			strcat(buff," ok\n\r");
			break;
		case 404:
			strcat(buff," Not Found\n\r");
			break;
                case 503:
			strcat(buff," Service Unavailable\n\r");
		default:
			printf("error");
			return 0;
	}
	strcat(buff,"Server:MYHTTP/1.0\n\r");
	strcat(buff,"Connect-Length:");
	struct stat st;
	stat(path,&st);
	sprintf(buff+strlen(buff),"%d",st.st_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);
	return 1;
}

void SendClient(int c,char* buff)
{
	/*GET/INDEX.HTML  HTTP/1.1 */
	int status = 200;
	char *p = strtok(buff," ");
		  p = strtok(NULL," ");
    char path[128] = "/var/www/html";
	strcat(path,p);

	int fd = open(path,O_RDONLY);
	if(fd == -1)
	{
		status = 404;
		fd = open("/var/www/html/404.html",O_RDONLY);
		if(fd == -1)
		{
			return;
		}
		//status = 404;
	}

	if(!SendHead(c,path,status))
	{
		close(fd);
		return;
	}

	while(1)
	{
		char file_buff[128] = {0};
		int n = read(fd,file_buff,127);
		if(n <= 0)
		{
			close(fd);
			break;
		}

		send(c,file_buff,n,0);
	}

}

int main()
{
	int listenfd = socket(AF_INET,SOCK_STREAM,0);
		assert(listenfd != -1);

		struct sockaddr_in ser,cli;
		memset(&ser,0,sizeof(ser));

		ser.sin_family = AF_INET;
		ser.sin_port = htons(8080);
		ser.sin_addr.s_addr = inet_addr("192,168,1.154");

		int res = bind(listenfd,(struct sockaddr*)&ser,sizeof(ser));
		assert(res != -1);

		listen(listenfd,5);//已经完成连接的最大个数

		while(1)
		{
			int cli_len = sizeof(cli);
			int c = accept(listenfd,(struct sockaddr*)&cli,&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);

			SendClient(c,buff);
		}

			close(listenfd);
			return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值