【前端基础】2.HTTP协议详解

视频链接
重要性:无论是用webservice,还是rest做大型框架,都离不开HTTP认证。甚至可以简化的说:webservice = http协议 + xml ; rest = HTTP协议 + json ; 各种API也一般是用 http + XML/json来实现的。往小说网站做采集,小偷站也需要对HTTP协议有所了解。另外,对HTTP协议有了解后,学习Ajax是非常容易理解的。

什么是协议:
计算机中的协议和现实中的协议是一样的,一式两份/多份,双方/多方都遵从共同一个规范,这个规范就可以称为协议。

计算机之所以能全世界互通,协议功不可没,如果没有协议,计算机各说各话,根本谁都听不懂谁。
(协议:ftp,http,stamp,psp,tcp/ip 协议)

HTTP协议的工作流程:
0:原始状态:客户端与服务器之间没有关系。
http流程0什么叫连接?连接就是网络上的虚拟电路。
http流程1
http流程2
http流程3HTTP请求信息与响应信息的格式

GET
POST

请求:
(1)请求行(请求方法 路径 协议)
(2)头信息(格式为key:value)
(3)主体信息(可选)(发送内容)

请求方法:GET POST PUT DELETE TRACE OPTIONS
所用的协议:目前一般是HTTP/1.1 0.9和1.0已经基本不用。

例:

POST /0606/02php HTTP/1.1
Host:localhost
Content-type:application/x-www-form-urlencode
Content-length:5

Age=3

响应
相应行(协议 状态码 状态文字)
响应头信息(格式为key: value)
主体信息(也可能没有)
例:

http/1.1 200 OK
Content-type:text/html
Content-length:5

hello

请求方法虽然是HTTP协议里规定的,但WEB SERVICE未必允许或支持这些方法。
不支持

HEAD:和GET基本一致,只是返回内容。
比如我们只是确认一个内容(比如照片)还正常存在,不需要返回照片的内容,这时用HEAD比较合适。
TRACE:当用了代理上网,比如用代理访问 new.163.com 。你想看看代理有没有修改你的HTTP请求,可以用TRACE来测试一下 ,163.com 的服务器就会收到请求方法。
OPTIONS:是返回服务器哪些方法是可用的。

Option

状态码,状态文字:
状态码,是用来反应服务器相应情况的。
状态文字,是用来描述状态码的,便于观察。
最常见的如 200 OK,404 NOT FOUND。

状态码定义说明
1XX信息接收到请求,继续处理
2XX成功操作成功,理解和接受
3XX重定向为了完成请求,必须采取进一步措施
4XX客户端错误请求的语法有错误,或不能完全被满足
5XX服务端错误服务器无法完成明显的请求

注:
200 服务器成功返回网页。
301/2 永久/临时重定位。
304 Not Modified 未修改 取缓存,减轻服务器压力,客户端告诉服务器,我有这个图片。
307 重定向中保持原有的请求数据(POST)。

404 请求的页面不存在。
503 服务器暂时不可用。
500 服务器内部错误。

Socket编程发送GET请求

http.class.php

//http请求类的接口
interface Proto{
	//连接url
	function conn(&url);
	//发送get查询
	function get();
	//发送post查询
	function post();
	//关闭连接
	function close(); 
}

class Http implements Proto{
	const CRLF="\r\n";
	protected &error=-1;
	protected &errser=' ';
	protected &respose=' ';
	
	protected &url=null;
	protected &version='HTTP/1.1';
	protected &fh=null;
	
	protected &line=array();
	protected &header=array();
	protected &body=array();
	
	public fuction _construct(){
		&this->conn(&url);
		&this->setHeader('Host:'.&this->url['host']);
	}
	
	//此方法负责写请求行 
	protected function setLine(&method){
		&this->line[0]=&method.' '.this->url['path'].&this->version;
	}
	
	//此方法负责写头信息
	public function setHeader(&headerline){
		this->header[]=&headerline;
	} 
	
	//此方法负责写主体信息
	protected function setBody(&body){
	}
	
	//连接url
	public function conn(&url){
		&this->url=parse_url(&url);
		if(!isset(&this->url['post'])){
			&this->url['port']=80;
		}
		&this->fh=fsockopen(&this->url['host'],this->url['port'],&this->error,&this->errser,3);
	} 
	
    //发送get请求的数据
	public function get(){
		&this->setLine('GET');
		&this->request();
		return &this->respose;
	}
	 
	//发送post查询的数据
	public function post(){
	}
	
	//发送post查询的数据
	public function request(){
		//把请求行,头信息,实体信息,放在一个数组中,便于拼接
		&req=array.merge(&this->line,&this->header,array(' '),&this->body,array(' '));
		//print_r(&req)
		&req=implode(self::CRLF,&req);
		//fecho &req;exit;
		fwrite(&this->fh,&req);
		while(!feof(&this->fh)){
			&this->respose.=fread(&this->fh,1024);
		}
		&this->close;//关闭连接 
	}	
	
	//真正连接
	public function close(){
	} 
}


&url='http://news.163.com/13/0613/09/9187CJ4COOO14JB6.html';
&http=new Http(&url);
echo &http->get();
                      

Socket编程发送POST请求,批量发帖

http.class.php

//http请求类的接口
interface Proto{
	//连接url
	function conn(&url);
	//发送get查询
	function get();
	//发送post查询
	function post();
	//关闭连接
	function close(); 
}

class Http implements Proto{
	const CRLF="\r\n";
	protected &error=-1;
	protected &errser=' ';
	protected &respose=' ';
	
	protected &url=null;
	protected &version='HTTP/1.1';
	protected &fh=null;
	
	protected &line=array();
	protected &header=array();
	protected &body=array();
	
	public fuction _construct(){
		&this->conn(&url);
		&this->setHeader('Host:'.&this->url['host']);
	}
	
	//此方法负责写请求行 
	protected function setLine(&method){
		&this->line[0]=&method.' '.this->url['path'].&this->version;
	}
	
	//此方法负责写头信息
	public function setHeader(&headerline){
		this->header[]=&headerline;
	} 
	
	//此方法负责写主体信息
	protected function setBody(&body){
		&this->body=http_build_query(body);
	}
	
	//连接url
	public function conn(&url){
		&this->url=parse_url(&url);
		if(!isset(&this->url['post'])){
			&this->url['port']=80;
		}
		&this->fh=fsockopen(&this->url['host'],this->url['port'],&this->error,&this->errser,3);
	} 
	
    //发送get请求的数据
	public function get(){
		&this->setLine('GET');
		&this->request();
		return &this->respose;
	}
	 
	//发送post查询的数据
	public function post(&body=array()){
		&this->setLine('POST');
		&this->setHeader('Content-type:application/x-www-form-urlencode');
		//设计主体信息 ,与GET不一样的地方 
		&this->setBody(&body);
		&this->setHeader('Content-length:'.strlen(&this->body[0]));
		&this->request();
	}
	
	//发送post查询的数据
	public function request(){
		//把请求行,头信息,实体信息,放在一个数组中,便于拼接
		&req=array.merge(&this->line,&this->header,array(' '),&this->body,array(' '));
		//print_r(&req)
		&req=implode(self::CRLF,&req);
		//fecho &req;exit;
		fwrite(&this->fh,&req);
		while(!feof(&this->fh)){
			&this->respose.=fread(&this->fh,1024);
		}
		&this->close;//关闭连接 
	}	
	
	//真正连接
	public function close(){
		fclose(&this->fh);
	} 
}


set_time_limit(0);
&url='http://liangyue.net.cn/0523/?';

&str=str_shuffle("abcdefghijkildj14259605");

for(&i=1;&i<10;i++){
	&tit=substr(&str,0,5);
	&con=substr(&str,6,8);
	
	&http=new Http(&url);
	&http->post(array('tit'=>&tit,'con'=>&con,'submit'=>留言));
	echo &tit,'-----------',&con,'<br />';
	usleep(2000);
}

http协议模拟登录发贴

http.class.php

//http请求类的接口
interface Proto{
	//连接url
	function conn(&url);
	//发送get查询
	function get();
	//发送post查询
	function post();
	//关闭连接
	function close(); 
}

class Http implements Proto{
	const CRLF="\r\n";
	protected &error=-1;
	protected &errser=' ';
	protected &respose=' ';
	
	protected &url=null;
	protected &version='HTTP/1.1';
	protected &fh=null;
	
	protected &line=array();
	protected &header=array();
	protected &body=array();
	
	public fuction _construct(){
		&this->conn(&url);
		&this->setHeader('Host:'.&this->url['host']);
	}
	
	//此方法负责写请求行 
	protected function setLine(&method){
		&this->line[0]=&method.' '.this->url['path'].'?'.&this->url['query'].' '.&this->version;
	}
	
	//此方法负责写头信息
	public function setHeader(&headerline){
		this->header[]=&headerline;
	} 
	
	//此方法负责写主体信息
	protected function setBody(&body){
		&this->body=http_build_query(body);
	}
	
	//连接url
	public function conn(&url){
		&this->url=parse_url(&url);
		//判断端口 
		if(!isset(&this->url['post'])){
			&this->url['port']=80;
		}
		//判断query
		if(!isset(&this->url['query'])){
			&this->url['query']=' ';
		} 
		&this->fh=fsockopen(&this->url['host'],this->url['port'],&this->error,&this->errser,3);
	} 
	
    //发送get请求的数据
	public function get(){
		&this->setLine('GET');
		&this->request();
		return &this->respose;
	}
	 
	//发送post查询的数据
	public function post(&body=array()){
		&this->setLine('POST');
		&this->setHeader('Content-type:application/x-www-form-urlencode');
		//设计主体信息 ,与GET不一样的地方 
		&this->setBody(&body);
		&this->setHeader('Content-length:'.strlen(&this->body[0]));
		&this->request();
	}
	
	//发送post查询的数据
	public function request(){
		//把请求行,头信息,实体信息,放在一个数组中,便于拼接
		&req=array.merge(&this->line,&this->header,array(' '),&this->body,array(' '));
		//print_r(&req)
		&req=implode(self::CRLF,&req);
		//fecho &req;exit;
		fwrite(&this->fh,&req);
		while(!feof(&this->fh)){
			&this->respose.=fread(&this->fh,1024);
		}
		&this->close;//关闭连接 
	}	
	
	//真正连接
	public function close(){
		fclose(&this->fh);
	} 
}

require('./http.class.php');
&http=new Http('http://home.verycd.com/cp.php?ac=pm&op=send&touid=0&pmid=0');

&http->setHeder('Reccept:~~~~~~~~~~~~~~~~');
&http->setHeder('Reccept-Encoding:~~~~~~~');
&http->setHeder('~~~~~~~~~~~~~~~~~~~~~~~~')
&http->setHeder('~~~~~~~~~~~~~~~~~~~~~~~~')

&http->setHeder('Cookie:~~~~~~~~~~~~~~~~~');

&http->setHeder('Referer:~~~~~~~~~~~~~~~~');
&http->setHeder('User-Agent:~~~~~~~~~~~~~');


&msg=array(
'formhash'=>'4f23e777',
'message'=>'I am from robot',
'pmsubmit'=>'true', 
'pmsubmit_btn'=>'发送', 
'refer'=>'http://home.verycd.com/space.php?do=pm8filter=privatepm',
'username'=>'http接收'
);

file_put_contents('./res.html',&http->post(&msg));
echo 'ok'; 
 

以上的"~~~"均来自复制。

在这里插入图片描述在这里插入图片描述

referer头与防盗链

在这里插入图片描述
服务器是怎么样知道这个图片是在站外被引用。
在网站的统计结果,统计用户从何而来。

在Http协议中,头信息里,有一个重要的选项Referer
Referer:代表网页的来源,即上一页的地址
如果是直接在浏览器上输入地址,回车进来,则没有Referer头
这也是为什么服务器知道我们图片是从哪儿引用的,也知道客户是从哪个网页链接点进来的。

如何配置apache服务器,用于图片防盗链?
原理:在WEB服务器层面,根据http协议的referer头信息,来判断,如果来自站外,则统一重写到一个很小的防盗链提醒图片上去。

具体步骤:
1.打开apache重写模块 mod_rewrite
mod_write0
前面的 “#” 去掉,并重启 apache。

mod_write1
重启

  1. 在需要防盗的网站或目录,写 .htaccess 文件,并指定防盗链规则。

.htaccess.htaccess

如何指定?
分析referer信息,如果不是来自本站,则重写。
重写规则:
哪种情况重写:
(1)jpeg/jpg/gif/png图片。
(2)referer头与localhost不匹配时。
怎么重写:
统一rewrite到某个防盗链图片。

如何收集网络上的图片:
在这里插入图片描述
HTTP协议缓存控制
我们观察图片的下载,往往:
第一次请求时 200 OK。
第二次请求时 304 Not Modified 未修改状态。

解释:在网络上,有一些缓存服务器,另外,浏览器自身也有缓存功能。
基于一个前提——图片不会经常改动,服务器在返回200的同时,还返回该图片的“签名”——Etag,(签名可以理解图片的“指纹”)
当浏览器再次访问该图片时,去服务器检验“指纹”,
如果图片没有变换,直接使用缓存中的图片,这样减轻了服务器负担。

第一次请求头:
第一次请求头
第一次响应头:
第一次响应头第二次请求头:
第二次请求头

这两行的意思是:
如果自 “Tue , 18 Jun 2013 14:04:32 GMT"这个时间点以后,图片修改过,则重新请求。
如果该图片最新的Etag的值和If-None-Match的值不匹配,则重新请求。

第二次响应信息
如果是304,就意味着浏览器从本地取缓存,节省了图片在网络上传输的时间。

选学:
如果网站比较大,有N台缓存服务器,如何处理主服务器上的文件
(1)要不要缓存?
(2)缓存多久?

思考——这说明缓存服务器与主服务器之间,应该有一些协议,来说明这两个问题?
追问——用什么协议来说明这两个问题?
答——还是http协议,用头信息cache_control来控制

具体用法:
在主服务器打开apache的expires扩展,利用该扩展来控制图片css,html等缓存的生存周期。
在.htaccess中,具体语法如下:

ExpiresDefault "<base> [plus] {<num> <type>}*"
ExpiresByType type/encoding "<base> [plus] {<num> <type>}*"

ExpiresDefault 是设置默认的缓存参数。
ExpiresByType 是按照文件类型来设计独特的缓存参数。
我吗用第2种来做测试jpg图片设置1个月的生存周期。
后面4个参数怎么理解?
Base:基于哪个时间点来计算缓存有效期。
Access/now:基于请求/响应的那一瞬间,比如从此到一个月后。
modification:基于被请求文件的最后修改日期,比如:被最后修改日期的一周内仍然有效。

Num:缓存时间的大小 30
Type:缓存时间的单位 天

在这里插入图片描述
在这里插入图片描述

如果这是在集群环境里,缓存服务器得到此图片,将会认为一个月有效,减轻了主服务器的负担。

我们能否设置服务器,不让用缓存?
比如有些个人信息不允许服务器缓存,必须到主服务器去请求。
Catrol-cache: no-store,must-revalidate;
可以利用apache的header模块。

HTTP内容压缩
原理:为了提高网页在网络上的传输速度,服务器对主体信息进行压缩。
如常见的gzip压缩,deflate压缩以及google chrome 的sdcn压缩。
http内容压缩服务器对页面进行了压缩,而content-length是”压缩后“的长度。

如何在apache启用压缩功能?
(1)开启deflate模块或gzip模块。
(2)在conf文件中,写如下代码。

<ifmodule mod-deflate.c>
Deflate CompressionLevel 6 #压缩级别为6,可选1-9,推荐6
AddOutputFilterByType DEFLATE text/plain #压缩文本文件
AddOutputFilterByType DEFLATE text/html #压缩html文件
AddOutputFilterByType DEFLATE text/xml #压缩xml文件
</ifmodule>

压缩压缩2

为什么要指定文件类型来压缩?
压缩也是要耗CPU资源的,图片/视频等文件,压缩效果也不好,一般压缩文本格式。

服务器是怎么知道我们浏览器支持gzip的
客户端允许一个Accept-Encoding头信息,与服务器协商
chorme支持四种压缩方式:
谷歌火狐支持两种:
在这里插入图片描述
小技巧:当我们在采集时,可以不发送Accept_Encoding信息,这样采集直接是源码,也可以采集gzip(提高速度),再用PHP解压gzip的内容。

HTTP持久连接+分块传输——>反向Ajax
反向ajax又叫comet ,server push 服务器推技术。
应用范围:网页聊天服务器,新浪微博在线聊天,google mail 网页聊天都有用到。

原理:一般来说,HTTp协议的特点,连接<->断开
具体什么时间断开?
服务器响应 content-length收到指定length长度的内容时,也就断开了。
在http1.1协议中,允许你不写content-length。比如要发送的内容长度确实不知道。
这时,需要一个特殊的content-type:chuncked。

分块传输的原理是这样的:
123 H\r\n
123H个长度的内容传输给客户端…\r\n

41 H\r\n
浏览器继续接收41H长度的内容…\r\n
0\r\n (服务器说内容发完了)

例:
分块链接
及时联系,在线交流:
Ajax0Ajax1

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值