HTTP协议
HTTP,超文本传输协议 (HTTP-Hypertext transfer protocol)
什么是协议?
一种约定,一套语法,一系列规则!
HTTP,用于规范 在b/s架构中,浏览器与服务器之间信息数据交换的规则!
HTTP,应用层的协议!不负责连接,浏览器与服务器建立的一个tcp的连接!
http协议,需要对,请求数据格式,与响应数据数据格式做规范!
利用典型的抓包工具!
利用 firebug演示:
ie:开发人员工具!(ie9自带),否则可以使httpwatch的插件!
chrome
HTTP请求协议
请求数据,应该由三部分组成:
分别是:请求行(请求数据的第一行),请求头,请求主体
请求行
请求数据的第一行,内有三个信息组成
是:请求方式 请求URL 协议版本
请求头
浏览器向服务器发送一些状态数据,标识数据等等。
可以有多个请求头信息组成!
每个头信息,占用一行!
头信息的组成有两部分:
标识: 值
例如:
User-Agent: firefox//表示发送请求的浏览器(请求代理端)是firefox
Host: shop.100.com//表示请求的主机域名(基于域名的虚拟主机就是靠这个头判断的)
Cookie:name=itcast//浏览器携带的cookie数据。
注意,请求头信息,需要使用一个空行结束!
请求主体
请求代理端项服务器端,发送的请求数据!
典型的就是POST形式发送的表单数据!
get请求,没有请求主体部分!get数据是在请求行中的url上进行传递的!
一个最典型的get请求:
注意:请求数据的每一行,要求使用回车换行结束!\r\n
模拟请求
模拟浏览器!
一门支持网络编程的语言,就可以完成请求的模拟!
PHP支持网络编程,可以建立网络连接!
模拟get请求
先连接上目标服务器
利用php的函数:fsockopen,可以建立一个socket或者internet连接!
典型的需要使用地址IP,和端口才可以!
成功后,返回一个支持数据传递的 流stream类型的资源!
将符合HTTP协议中get请求方式的数据发送给服务器端即可
构建get格式的数据!
发送到服务器
利用刚刚建立的流连接通道!需要使用一个函数fwrite,将数据写(发送)到目标服务器上。
写入的数据量 = fwrite(连接,内容)
此时,请求已经发送到目标服务器上!
等待服务器响应
并处理响应数据
利用函数 fgets来接收响应数据!
fgets,一次接受一行!
接收的数据 = fgets(浏览器与服务器的连接)
使用循环获得响应数据!
条件是,判断数据是否还有,利用feof()函数可以判断数据是否还存在!
是否到结尾 = feof(连接流资源)判断是否到数据流的结尾
没到结尾循环接续:
模拟POST请求
大体上都一致!
区别在于,post需要请求时发送请求数据!此时需要操作请求主体才可以!
与url上传递数据的格式几乎是一样的!
增加上请求主体:
除此之外:还要再请求头上,标识出请求主体的必要信息:
Content-Type表示请求主体数据类型
Content-Length 请求主体的数据长度(字节为单位)
HTTP响应协议
可见,响应数据也是由三部分组成
响应行,响应头,响应主体
响应行
三部分组成第一行:
协议版本 状态码 状态消息
HTTP/1.1 200 OK
其中状态码,与状态消息,一一对应!表示当前请求的响应结果是啥:
200 ok 表示 请求成功!
应该存在其他的状态码:
典型的:
1xx:消息
2xx:成功
3xx:请求被重定向
4xx:浏览器端错误
5xx:服务器端错误
典型:
500 服务器内部错误
404 请求的页面没有找到
403 没有权限
200 请求成功
参考:
响应头
服务器,需要 告知浏览器知道的一些信息
典型的:
Content-Type: text/html 内容类型,告知浏览器接下来发送的响应主体数据是什么格式!
Content-Length: 响应主体数据的长度!
Date: 响应的时间。GMT时间!
需要有个一空行!
响应主体
主要的响应数据,在浏览器的主体区域显示的数据都是相应主体!
phpecho
php标记之外的html代码。都是主体主体!
注意,每行,包括相应行和响应头,都需要一个 \r\n结尾
操作响应
对于php来讲:
使用header函数操作响应头
输出函数输出相应主体!
例如:
利用header函数,操作响应头,设置cookie变量!
http下载
下载,将服务器端的数据,保存到浏览器端!
http下载,就是将原本应该在浏览器上打开的数据数据,让浏览器保存起来即可!
我们服务器需要工作:
1, 将需要下载的内容输出到浏览器!
2, 告知浏览器,接收到的响应数据应该保存起来!、
利用一个响应头,Content-disposition: 告知浏览器内容的处理方法:
Content-disposition: attachment 将响应数据作为附件来对待!
http下载,只是下载的响应主体!
content-type
content-length
content-disposition
content:响应主体!
典型的下载图片
告知以附件方式处理:
并且输出图片的内容!
使用函数 readfile。读取一个文件内容(不限于文本文件,二进制文件也可以读),并且输出!
控制下载的文件名
增加一个子选项即可:
完善:
处理下载的内容类型
获得下载文件的类型MIME!
获得任意文件的MIME类型:
利用php的fileinfo的扩展,专门用于获取文件的信息!
开启扩展:
调用相应的函数获取文件的MIME信息:
finfo_open()
finfo_file();
curl:client URL
php的专门用于模拟请求的扩展!
(curl,独立工具,php支持curl库而已)
使用之前开启扩展:
curl扩展提供了一些列的函数,用于模拟url请求:
步骤
初始化一个curl工具
curl_init()
设置请求选项
curl_setopt(curl资源, 选项,选项值)
需要设置请求url
设置是否是post提交(默认是get)
如果是post提交,典型需要制定post数据!
如果需要显示响应头信息
与cookie相关的参数:用于模拟登录的!
记录cookie的文件:
请求时携带的cookie文件:
利用 cookie的操作,可以完成模拟请求的模拟登录!
发出请求
curl_exec(curl资源)执行请求
关闭资源
curl_close();
控制缓存(浏览器的缓存)
控制的浏览器端的缓存
典型的响应头,Expires
告知浏览器,当前你收到的响应数据应该的有效期到什么时候!
header()函数完成响应头的设置:
注意,此时的时间应该是一个格林威治平时
| Tue, 19 Nov 2013 07:27:14 GMT |
因此,Expires也是GMT时间:
gmdate();与date功能一致,将一个时间戳格式化成一个时间!date格式成本地时间(带时区的)。而gmdate格式化成一个GMT时间!
传输的格式:
星期, 日 月 年 时:分:秒 GMT
D, d M Y H:i:s GMT
可以通过expires 来控制页面在浏览器上缓存多久:
强制浏览器不缓存:
额外的,缓存控制:
Cache-Control : no-store no-cache must-revalidate
常见的主要是控制浏览器不缓存:
防止盗链
利用 请求时携带的请求头:
referer:表示当前请求的来源!
只要在请求图片的响应,判断一下当前的请求是否是来源本站即可!
得到来源。判断来源!
可以在Apache上,或者 php上都可以!
对于图片的请求都是用php生成!
通过判断$_SERVER[‘HTTP_REFERER’] 是否是当前网站!
典型的使用 strpos()某个字符串,在另一个字符串中第一次出现的位置。
返回值是:位置。如果不存在,则返回false!
fsockopen模拟GET,POST请求代码
<?php
//get方式的请求行
//GET /test.php HTTP/1.1
//post方式的请求行
//POST /index.php?p=back&c=Admin&a=signin HTTP/1.1
//GET /test.php HTTP/1.1\r\n
//Host:shop.100.com\r\n
//User-Agent:firefox\r\n
//\r\n
$host_ip = '127.0.0.1';
$port = '80';
if (!$link = fsockopen($host_ip, $port)) {
//连接失败
die('连接失败');
}
//var_dump($link);
//构建get请求字符串数据
$request_str = 'GET /test.php HTTP/1.1' . "\r\n";//请求行
//请求头
$request_str .= 'Host: shop.100.com' . "\r\n";//请求主机
$request_str .= 'User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0' . "\r\n";//请求代理标识,模拟的firefox
//请求头以空行结束
$request_str .= "\r\n";//空行
//没有请求主体
//发请求
$result = fwrite($link, $request_str);
//var_dump($result);
//等待接收响应数据
echo '<pre>';
echo fread($link, 500);
//while (!feof($link)) {
// echo fgets($link);
//}
//--------------------------------------------------------分割线-----------------------------------------------------------------
//post数据
$admin_name = 'admin';
$admin_pass = '1234abcd';
$post_data = 'username='.$admin_name . '&password='.$admin_pass;
//username=admin&password=1234abcd
//构建post请求字符串数据
$request_str = 'POST /index.php?p=back&c=Admin&a=signin HTTP/1.1' . "\r\n";//请求行
//请求头
$request_str .= 'Host: shop.100.com' . "\r\n";//请求主机
$request_str .= 'User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0' . "\r\n";//请求代理标识,模拟的firefox
//post数据相关的请求头
$request_str .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n";//post主体数据类型
$request_str .= 'Content-Length: ' . strlen($post_data) . "\r\n";
//请求头以空行结束
$request_str .= "\r\n";//空行
//请求主体部分
$request_str .= $post_data;//不需要\r\n
//发送!
fwrite($link, $request_str);
//获得相应数据
echo '<pre>';
//echo fread($link, 8000);
while (!feof($link)) {
echo fgets($link);
}