原理篇
超文本传送协议 (HTTP-Hypertext transfer protocol) 是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。请求所用协议目前一般是HTTP/1.1。
一、重要性:无论是webservice,还是REST做大型架构,都离不开对HTTP协议。
http协议简单说:webservice = HTTP协议 + XMLREST = HTTP协议 + JSON
二、HTTP请求信息和格式
1)、请求行
请求方法:GET、POST、HEAD、PUT、TRACE、OPTIONS。如果只需要判断URL是否200则更适应用HEAD,它不会返回content,只有head,TRACE会跟踪中间经过的路由IP,不是所有的协议服务器都支持,可试试用OPTIONS 返回可以用协议。
2)、请求头信息:格式key:value
3)、请求主体:要发送的内容
使用telnet进行HTTP操作:
1、telnet 域名 端口
2、ctrl+]
3、回车进入回显编辑界面
发送GET请求头示例:
POST /post.php HTTP/1.1
Host: localhost
发送POST请求头示例:
POST /post.php HTTP/1.1
Host: localhostContent-type: application/x-www-form-urlencodeContent-length:16
username=gxd&a=2
一个浏览器的请求头会有很多的内容,所以你要发送更多头内容可以打开网页进行参考,如下
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding:gzip,deflate,sdch Accept-Language:zh-CN,zh;q=0.8 Cache-Control:max-age=0 Connection:keep-alive Cookie:BDUSS=zk4anNXWmxDd2hJcm5JakxjY2hsRGN4ZXBYa1BjMjlvV1NySUdwcHdlN1RhfmRUQVFBQUFBJCQAAAAAAAAAAAEAAAC2a4MKdGhhdDMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANPez1PT3s9TZ; BAIDUID=CE81919996FE28E7ADB09C1663B093B6:FG=1; H_PS_BABANNER=5; H_PS_BDC=1; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; BD_CK_SAM=1; BDRCVFR[T31KpgKciPc]=mk3SLVN4HKm; BD_HOME=1; H_PS_PSSID=1453_7800_9143_6505_6017_8592_9119_7825_8939_7798_8767_7963_9193_8448_8973_9051_9024_9188_9170; BD_UPN=123143 Host:www.baidu.com User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36
2、响应行
状态码和状态文字:
状态码表示服务器响应情况,状态文字是方便人观察
1xx 接收到信息,继续处理
2xx 操作成功,理解和接受
3xx 重定向,为了完成请求,必须采取进一步措施
4xx 客户端错误,请求的语法有错误或不能完全被满足
5xx 服务器错误,服务器无法完成明显有效的请求
常见状态码:
200 - 服务器成功返回网页
301/302 - 永久/临时重定向,PHP中的header('Location:http://www.baidu.com')此时默认是302,如果要指定301则最后加两个参数true,301。301永久重定向对不会对SEO有影响,而且网页A的关键词排名和PR级别都会传达给网页B,网站更换了域名,表示本网页永久性转移到另一个地址,对于搜索引擎优化|SEO来说,给搜索引擎一个友好的信息,告诉它此页面已永久重定向,避免搜索引擎找不到页面。注意定向POST请求后,POST数据会丢失,
可以使用307重定向保留POST请求,跳转后referer还是保留之前的而不是做302跳转的Url
304 - Not Modified 资源未被修改,此时浏览器会优先取缓存中的数据。原理:如果浏览器中有缓存该资源,则在请求的header中会带上:
If-Modified-Since
:时间和
If-None-Math
:编号;当服务器收到请求后会根据
If-None-Math编号
与资源修改时间等计算出的编号作对比,如果相同,则会在response headers中返回Etag和Last-Modified,返回状态304且不会返回主体信息;客户端发现是304
,则是就取缓存中数据
404 - 请求网页不存在
503 - 服务器暂时不可用
500 - 服务器内部错误
实 战
首先确定服务器是否打开了php_socket扩展
第一步:fsockopen(url,......)
第二步:拼接请求信息,注意不同平台的换行符,可以用常量
PHP_EOL获取,post参数可以用
http_build_query拼接
发送POST请求头示例:
POST /post.php HTTP/1.1
Host: localhostContent-type: application/x-www-form-urlencodeContent-length:16(注意这里多了一行)username=gxd&a=2
第三步:write进打开的socket端口
fwrite($fsocket,$request)
//$request是第二步中拼接的请求信息
第四步:读返回的内容
while(!eof($fsocket))
{
$content .= fread($fsocket,1024)l
}
第五步:关闭socket连接
二、HTTP协议与cookie
1、首先登录系统,在post数据时复制下header信息
2、拼接请求header
3、写入请求头:fwrite($fs, $request);
4、接收服务器响应,并前往网站观察是否成功
while
(!feof($fs))
{
$content .= fread($fs, 1024);
}
file_put_contents(
'./text.txt'
,$content);
我们应该怎么防范机器人呢?
1、添加验证码是最有效的。
2、添加token令牌验证可以增加机器人模拟难度。
3、 根据IP频率做判断(
$_SERVER['HTTP_CLIENT_IP']它可以在HTTP请求中伪造,$_SERVER['REMOTE_ADDR']
是
无法伪造的)如1分钟最多多少次,每次间隔至少多长。
三:referer头与防盗链
如果<img src="QQ空间某图片">会出现什么?
服务器是怎么知道是被外网引用的呢?
网站流量统计又是怎样实现从哪来到本网站的呢?
没错,就是通过referer判断的
a)、配置appche实现防盗链,如果来自站外,则重写到一个防盗链的图片上去,首先打开rewrite模块,并将配置中的AllowOverride None全为设置为All,再在目录下创建文件.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} .*\.(jpg|gif|png) [NC]
RewriteCond %{HTTP_REFERER} !localhost [NC]
RewriteRule .* /denied_request.png [NC]
NC表示不区分大小写
然后编写html,<img src="./xx.jpg">访问测试
b)、配置nginx实现防盗链:
防盗链不仅可以保护内容,
更重要的是减轻服务器负担
如果要采集图片也很简单,请求header中添加refere项目即可
优化
一、HTTP协议与缓存控制
浏览器也会有缓存
观察一张图片的Response Headers
在服务器打开appache的expires扩展,利用它来控制图片、css、js、html等文件是否缓存及缓存时间
设置说明
ExpiresDefault "<base> [plus] {<num> <type>}*" 设置默认缓存参数
ExpiresByType type/encoding "<base> [plus] {<num> <type>}*" 按照文件类型来设置缓存参数
我们用第二中来给jpg图片设置一个月的生存周期,
在.htaccess文件
ExpiresActive On
ExpiresByType image/jpeg "access plus 30 days"
我们能否设置服务器不让用缓存呢?
Control-cache:no-store,must-revalidate;
首先打开appche扩展:mod_headers
然后在.access中添加
<FilesMatch "\.(gif)$">
header set
Control-cache "no-store,must-revalidate"
</FilesMatch>
二、HTTP内容压缩
打开一个网页观察response,同时保存源代码发现大小远大于Content-Length
解释:为了提高网页在网络上的传输速度,服务器对主体信息进行压缩,Content-length是压缩后的大小值
常见的有gzip压缩、deflate压缩、compress压缩、sdch压缩
使用appache的
deflate压缩:
1、首先打开mod_deflate模块
2、在http.conf中添加如下配置
<ifmodule mod_deflate.c>
DeflateCompressionLevel 6 #压缩级别1-9,推荐为6,它和消耗CPU资源成正比
AddOutputFilterByType DEFLATE text/plain #压缩文本文件
AddOutputFilterByType DEFLATE text/html #压缩HTML文件
AddOutputFilterByType DEFLATE text/xml #压缩XML文件
AddOutputFilterByType DEFLATE text/css #压缩CSS文件
AddOutputFilterByType DEFLATE text/javascript #压缩javascript文件
</ifmodule>
为什么要指定文件类型压缩?----首先压缩耗CPU,还有图片/视频等文件压缩效果不好
使用Nginx压缩:
压缩在高并发的优势尤为重要,假设网易的pv是10亿,压缩后每天大概可少4000G流量,节省了40%流量
浏览器怎么知道我们的浏览器支持gzip的?请看请求header
技巧:当我们在采集时可以不发送Accept-Encoding信息,活动解压缩的麻烦,如果你带宽底也可以加上。
三、分块传输,持久连接与反向ajax
反向Ajax又叫comet,server push 服务推技术
应用范围:在线聊天。
原理:一般而言,HTTP协议的特点,连接然后断开
服务器响应content-length,当收取到length长度时就断开了
在HTTP1.1协议中允许你不写content-length,比如要发送的内容长度确实不知道
这时需要一个特殊的内容类型:Content-Ttype:chunked
分块传输原理:
123号\r\n
....
123
其中 最后结束以 0\r\n 表示传输完毕
示例:
<?php
set_time_limit(0);//不限时运行脚本
ob_end_flush();//关闭缓存
for($i=0;$i<10;$i++){
echo 'index:'.$i.'<br/>';
flush();
sleep(1);
}
这玩意儿有个问题是浏览器一直处理加载状态中,汗。。。
一般实现在线聊天有三种方式:ajax轮训,服务推,flash
实验中所使用的代码:
一:PHP+SOCKET:模拟GET请求
<?php
$url = 'http://news.163.com/14/1011/18/A89VFIGC00014JB5.html';
$urlParse = parse_url($url);
$fs = fsockopen($urlParse['host'],80,$error);
//注意后面还有两个回车符
$header = "GET {$urlParse['path']} HTTP/1.1".PHP_EOL.
"Host: {$urlParse['host']}".PHP_EOL.PHP_EOL;
fwrite($fs, $header);
$response = '';
while (!feof($fs))
{
$response .= fread($fs, 1024);
}
fclose($fs);
exit($response);
二:PHP+SOCKET 模拟POST+cookie请求
<?php
$url = '';
$urlParse = parse_url("http://www.xxxxxxxxxx.com/comment/post");
$errno = null;
$fs = fsockopen($urlParse['host'],80,$errno);
if(!$fs)
{
exit('连接socket失败:'.$errno);
}
$request = 'POST '.$urlParse['path'].' HTTP/1.1'.PHP_EOL.
'Host:www.xxxxxxxxxxx.com'.PHP_EOL.
'Accept:application/json, text/javascript, */*; q=0.01'.PHP_EOL.
'Accept-Encoding:gzip,deflate,sdch'.PHP_EOL.
'Accept-Language:zh-CN,zh;q=0.8'.PHP_EOL.
'Connection:keep-alive'.PHP_EOL.
'Content-Length:31'.PHP_EOL.
'Content-Type:application/x-www-form-urlencoded; charset=UTF-8'.PHP_EOL.
'Cookie:pgv_pvi=2390898688; PHPSESSID=dukm7v9d59ulev6ejk6s09m973; pgv_si=s442598400; _gat=1; skey=4l8r20sqh503l7f3f1g8tfcomr; uin=Oo16455; CNZZDATA1253203474=1849606238-1413157070-http%253A%252F%252Fwww.baidu.com%252F%7C1413242121; Hm_lvt_19b0d62eab26a8ad83451a88f6bac4dd=1413157072,1413242123; Hm_lpvt_19b0d62eab26a8ad83451a88f6bac4dd=1413242234; _ga=GA1.2.892595638.1413157072'.PHP_EOL.
'Origin:http://www.xxxxxxxx.com'.PHP_EOL.
'Referer:http://www.xxxxxxxx.com/house/12006'.PHP_EOL.
'User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36'.PHP_EOL.
'X-Requested-With:XMLHttpRequest'.PHP_EOL.PHP_EOL.
'hid=12006&content=this is goods ';
fwrite($fs, $request);
$content = '';
while(!feof($fs))
{
$content .= fread($fs, 1024);
}
file_put_contents('./text.txt',$content);