一、网站访问流程
cgi与fastcgi区别
PHP-fpm :进程管理器
cgi是比较老的版本
fastcgi是cgi的升级版 提升了性能以及报头文
1、lnmp=linx nginx mysql php
2.nginx & apache区别[lamp]
1.nginx体积小,apache体积大
2.nginx扩展性好 apache扩展性差
3.nginx抗并发能力强 apache
如何我们对于的服务有没有启动
1.查看进程
ps aux | grep nginx
ps aux | grep mysqld
2.端口
netstat -ant | grep 80
netstat -ant | grep 3306
进程:
进程是一个软件运行的过程
主进程
子进程
3.php
启动模式
php-fpm : 配置文件 php-fpm.conf
php进程启动的用户
user
group
listen = 127.0.0.1:9000#监听端口
pm = dynamic#动态| static 静态
pm.max_children = 5 #开始多少个子进程
pm.start_servers = 2#开启多少个子进程
pm.min_spare_servers = 1 #最小空余进程
pm.max_spare_servers = 3#最大空余进程
pm.process_idle_timeout = 10s#超时时间
http请求的流程:
1、客户端主动发送请求的到服务端
请求分为:
请求行。【请求的路径】
请求头。【header】
空行 【区分请求的头部和主体】
请求的数据 【body】
http://localhost
header:content-type
data[user_name]=zhangsan&data[password]=123456
2、服务端接受到请求,处理
3、服务端把相关的数据返回回去,给客户端
状态行
响应头部
空白行
响应的数据
DEMO:
200 ok
header信息
返回的内容
二、网络协议
网络协议
传输层协议: 【 不同主机之间怎么传递数据 】
tcp和udp区别:
tcp: 可靠的网络协议
面向连接的,数据传输的可靠性比较高,适合传输大量的数据,速度慢。【发短信】
安全性较高
udp:不可靠的网络协议
不需要建立连接,直接发送数据,速度高于tcp传输,但是安全性低于tcp,
适合传输少量的数据【打电话】
协议概念:双方共同遵循的规则
http协议:无状态,无连接协议
请求
请求行
请求方式 GET|POST
请求文件
协议的名字和版本号
请求报文
消息体
如果你的请求方式是post里面是你的参数
回应
响应行
协议名和版本号
状态码
状态码描述
响应报文
响应内容
https:
http和https的区别:
http不安全https安全
https=http+openssl
七层协议:
应用层 【http】
表示层 【数据的转码 等】
会话层 [ 确定2个电脑之后如何进行会话,传输数据 ]
传输层 【 电脑和电脑直接如何传递数据 规定了两个电脑直接如何传递数据】
网络层 【电脑和电脑之间是通过ip进行通讯的 tcp/ip 】
数据链路层 【 对数据进行处理 变成01010 】
物理层 【电脑的硬件】
http协议是无状态、无连接的。 所以出现了会话控制。
会话控制:cookie和session,用来识别用户的
php运行的几种模式:
1、CLI server: php的命令行
2、apache模块
3、cgi和fastcgi
三、cooke 和 session & 本地缓存 & 跨域
session与cookie的区别
1、cookie 数据存放在客户的浏览器上,session 数据放在服务器上。
2、cookie 不是很安全,别人可以分析存放在本地的 COOKIE 并进行 COOKIE 欺骗
考虑到安全应当使用 session。
3、session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用 COOKIE。
4、单个 cookie 保存的数据不能超过4K,很多浏览器都限制一个站点
最多保存 20 个cookie。
5、所以个人建议:
将登陆信息等重要信息存放为 SESSION
其他信息如果需要保留,可以放在 COOKIE 中
session的运行原理
当第一次访问网站时,Seesion_start()函数就会创建一个唯一的Session ID,
并自动通过HTTP的响应头,将这个Session ID保存到客户端Cookie中。
同时,也在服务器端创建一个以Session ID命名的文件,用于保存这个用户的会话信息。
当同一个用户再次访问这个网站时,也会自动通过HTTP的请求头将Cookie中保存的
Seesion_id再携带过来,这时Session_start()函数就不会再去分配一个
新的Session ID,而是在服务器的
硬盘中去寻找和这个Session ID同名的Session文件,
将这之前为这个用户保存的会话信息读 出,
在当前脚本中应用,达到跟踪这个用户的目的
禁用 COOKIE 后 SEESION 还能用吗?
可以,
在存储 session 的文件中,生成 sessionID,通过 get 传参的方式将 sessionID
传到要实现 session 共享的页面,读取 sessionID,从而从 session 中获取数据
php 在储存 session 以什么形式存在
PHP 为 session 的存储提供了三种方式: 文件/ 内存/ 自定义存储,默认是使用文
件存储.在访问量大的网站上采用这种方式就不大合适,因为这样会导致大量的输入输
出的冗余.我们可以在 php.ini 更改配置文件或者 php 脚本中通过相应的函数来设置
session 文件的存储类型来改变 session 文件的存储形式
为什么有cookie & session
- cookie的参数
<?php
setcookie('name','ldy',time()*86400,'/','.ldyphp.top');
#键名、 值、 失效时间、 当前作用域、域名作用域]
?>
session的存储方式
session.save_path="D:\phpStudy\PHPTutorial\tmp\tmp" #存储在什么位置
session.save_handler = files #表明我们的session存储文件
-
详细操作
-
用户可以存session(已文件形式)?
可以 ,但 必须是访问量小的网站才可以
访问量大的网站,都存入memcache、redis缓存中
(访问量太大,如果已文件形式存入,系统将会瘫痪) -
什么是session共享
已缓存(memcache、redis)的形式存入session -
单点登录
四、接口安全
防刷
1 .ip地址限制(容易误杀)
<?php
$ipaddr = $_SERVER['REMOTE_ADDR'];//获取客户单的ip地址
$objreids = new Redis();
$objreids->connect("127.0.0.1",6379);
$key = $ipaddr; //获取键值
$count = $objreids->get($key); //获取调用了几次
$count = intval($count); //转化为整形
if($count > 10){
echo "调用次数超限制";
exit;
}
$count = $count+1; //每次存入都加一
$objreids->set($key,$count,86400);
//下面的代码是
echo "通过验证";
//你给我的是不是服务器给你的
//token有效期
$accessToken = $_GET['token'];
$objredis = new Redis();
$objredis->connect("127.0.0.1",6379);
$bol = $objredis->exists($accessToken);
if(!$bol){
echo "你的token过期";
exit;
}
echo "调用成功";
?>
2 .生成accessToken过期时间
1.accessToken是否存在 2.是否过期
防止ID重复出现
<?php
//防止出现重复
$num = uniqid();
$num=$num.rand(1000,9999);
$num = md5($num);
$objredis = new Redis(); //使用redis
echo $num;
$objredis->connect("127.0.0.1",6379); //链接redis
$objredis->set($num,1,60); //设置一个值 过期时间1分钟
?>
<?php
$url = "http://www.first.test.com/aa/demo07.php";
function send_get($url){
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
// 超时设置,以秒为单位
curl_setopt($curl, CURLOPT_TIMEOUT, 1);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
//执行命令
$data = curl_exec($curl);
return $data;
}
$accessToken = send_get($url);
//======================================================
$url = "http://www.first.test.com/aa/demo01.php?token=$accessToken";
$info = send_get($url);
var_dump($info);
?>
<?php
//token有效期
$accessToken = $_GET['token'];
$objredis = new Redis();
$objredis->connect("127.0.0.1",6379);
$bol = $objredis->exists($accessToken); //检测是否存在
if(!$bol){
echo "你的token过期";
exit;
}
echo "调用成功";
?>
3.redis的队列
限定每分钟调用次数(redis的队列)
<?php
$objredis = new Redis(); //使用redis
$objredis->connect("127.0.0.1",6379); //链接redis
$total=$objredis->llen('code'); //计算总长度
$sun =100-$total; //100-减去总长度
for($i=0;$i<$sun;$i++){
$num=rand(1000,9999); //设置随机数
$objredis->lpush('code',$num);//补足
?>
<?php
$objredis = new Redis(); //使用redis
$objredis->connect("127.0.0.1",6379); //链接redis
$bol=$objredis->rpop('code'); //弹出最后一个
if(!$bol){
echo '调用次数超限制';
exit;
}
echo '调用成功';
?>
签名(签名与客户端)
/*
$token ='111222';//token的秘钥
$arr=[
'name'=>'xiao',
'age'=>'20',
'sex'=>'1',
'token'=>$token,
];
kosrt($arr);//转换成name=xxx&sex=xxx&age=xxx的形式
$str=http_build_query($arr);
//函数的作用是使用给出的关联(或下标)数组生成一个经过 URL-encode
//的请求字符串。
$code=md5($str); //签名
unset($arr['token']);//(杀死token)传到服务器过程中,不能携带toeken值
$str1 = http_build_query($arr);
$str1 = $str1 '&code=$code';
*/
<?php
//客户端签名
$token="123456";
$arr=[
'name'=>"lisi",
"sex"=>'20',
'token'=>$token,
];
ksort($arr);//根据字母大小排序
$str=http_build_query($arr); //关联数组转成字符串
$token=md5($str);
unset($arr['token']);//销毁单个元素
$str1=http_build_query($arr);
$str1=$str1."&token=$token";
// echo $str1;
function send_get($url){
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
// 超时设置,以秒为单位
curl_setopt($curl, CURLOPT_TIMEOUT, 1);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
//执行命令
$data = curl_exec($curl);
return $data;
}
$url = "http://www.abc.com/aa/bb1.php?$str1";
?>
<a href="<?php echo $url ?>">aaa</a>
验签(验签与服务端)
/*
$arr = $_GET;
$token='111222'; //token的秘钥
data['name'] = $_GET['name'];
data['age'] = $_GET['age'];
data['sex'] = $_GET['sex'];
data['token'] = $token;
$code = $_GET['code']; //客户端的签名
kosrt($data);
$str=http_build_query($data);
$server_code = md5($str); //服务端的签名
if($code != $server_code){
echo '数据被篡改';
exit;
}
echo '请求通过';
*/
//服务端验签
$token="123456";
$data['name']=$_GET['name'];
$data['sex']=$_GET['sex'];
$data['token']=$token;
$code=$_GET['token'];//客户端签名
ksort($data);//根据字母排序
$data=http_build_query($data);//关联数组改成字符串
$token=md5($data);//服务端的签名
if($code!=$token){
echo "数据被穿改";
exit;
}
echo "验签成功";
调用接口
<?php
$url = "http://www.first.test.com/aa/demo07.php";
function send_get($url){
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
// 超时设置,以秒为单位
curl_setopt($curl, CURLOPT_TIMEOUT, 1);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
//执行命令
$data = curl_exec($curl);
return $data;
}
$accessToken = send_get($url);
//======================================================
$url = "http://www.first.test.com/aa/demo01.php?token=$accessToken";
$info = send_get($url);
var_dump($info);
?>
五、模式
单例模式
1、单一的连接数据库的实例【资源】==单例
2、解决的问题:提高我们网站的运行速度
3、三私一公(私有的静态变量、克隆方法、构造方法、公有的静态方法)
4、业务场景:PHP连接数据库
面向对象的代码规范(核心):=高内聚,低耦合=
面向对象的三大特性:分装、多态、继承
面向对象的五大基本原则:
单一职责原则SRP
开放封闭原则OCP
里式替换原则LSP
依赖倒置原则DIP
接口分离原则ISP
五大基本原则
面向对象的接口
单例模式(代码)
9.单例模式class Singleton
{
//创建静态私有的变量保存该类对象
static private $instance;
//防止使用new直接创建对象
private function __construct(){}
//防止使用clone克隆对象
private function __clone(){}
static public function getInstance()
{
//判断$instance是否是Singleton的对象,不是则创建
if (!self::$instance instanceof self) {
self::$instance = new self();
}
return self::$instance;
}
public function test()
{
echo "我是一个单例模式";
}
}
$sing = Singleton::getInstance();
$sing->test();
$sing2 = new Singleton(); //Fatal error: Uncaught Error: Call to private Singleton::__construct() from invalid context in
$sing3 = clone $sing; //Fatal error: Uncaught Error: Call to private Singleton::__clone() from context
工厂模式
- 思路:进去的是类名字,出来的是类的对象
9.[2]工厂模式:
//工厂模式 提供获取某个对象实例的一个接口,
//同时使调用代码避免确定实例化基类的步骤
//字符串类
class String {
public function write() {}
}
//Json类
class Json {
public function getJsonData() {}
}
//xml类
class Xml {
public function buildXml() {}
}
//工厂类
class Factory {
public static function create($class) {
return new $class;
}
}
Factory::create("Json"); //获取Json对象
观察者模式
9【3】观察者模式
<?php
// 主题接口
interface Subject{
public function register(Observer $observer);
public function notify();
}
// 观察者接口
interface Observer{
public function watch();
}
// 主题
class Action implements Subject{
public $_observers=array();
public function register(Observer $observer){
$this->_observers[]=$observer;
}
public function notify(){
foreach ($this->_observers as $observer) {
$observer->watch();
}
}
}
// 观察者
class Cat implements Observer{
public function watch(){
echo "Cat watches TV<hr/>";
}
}
class Dog implements Observer{
public function watch(){
echo "Dog watches TV<hr/>";
}
}
class People implements Observer{
public function watch(){
echo "People watches TV<hr/>";
}
}
// 应用实例
$action=new Action();
$action->register(new Cat());
$action->register(new People());
$action->register(new Dog());
$action->notify();
六、算法
冒泡排序
时间复杂度:衡量一个算法运行的时间的多少 O(N^2)
空间复杂度: 数据在计算机里面存储的大小 O(1)
<?php
$arr = [8,100,3,5,6,90,10];
//外层for循环控制找多少次
for($i=0;$i<count($arr)-1;$i++){
//内层for循环获得所有数据里面的最大值
for($j=0;$j<count($arr)-$i-1;$j++){
//中间的if判断是否交换位置
if($arr[$j] > $arr[$j+1]){
$tmp = $arr[$j];
$arr[$j]=$arr[$j+1];
$arr[$j+1]=$tmp;
}
}
}
print_r($arr);
快速排序
业务场景:大数据排序
时间复杂度:衡量一个算法运行的时间的多少 O(nlogn)
空间复杂度: 数据在计算机里面存储的大小 O(1)
思路:
随便设置一个为0的坐标,比它小的放左边,比它大的放右边
然后临时 (左右)存放一下 ,最后通过递归把它合起来
function quick_sort($arr){
//判断是否小于1,是直接跳出循环,不是继续循环
if(count($arr) <=1){
return $arr;
}
$num= $arr[0]; //设置一个随机数为下标
$left = array(); //定义一个数组(左)
$right = array();//定义一个数组(右)
//从中间劈开 分别循环左边和右边
for($i=1;$i<count($arr);$i++){
if($arr[$i] < $num){
$left[]=$arr[$i];
}else{
$right[] = $arr[$i];
}
}
//不断的递归循环 ,直到剩下最后一个数 跳出循环
$left = quick_sort($left);// 3 5, 6
$right = quick_sort($right);
//合并 并返回 合并的值
return array_merge($left,array($num),$right);
}
二分查找
业务场景:警察查找你的身份证号
$nums = [1, 2, 3, 4, 5, 6];
# 0, 1,2, 3, 4, 5 下标
//你查找的数
$num=5;
$start = 0; //启始位置
$end = count($nums)-1; //当前总长度-1
echo binary_search($nums,$num,$start,$end);
function binary_search($nums,$num,$start,$end){
$mid = floor(($start+$end)/2);//向下取整 2
$midNum = $nums[$mid]; // $mid为2 ,$nums找下标为2的数 也就是3
if($num < $midNum){
$end = $mid-1;
return binary_search($nums,$num,$start,$end);
}elseif($num > $midNum){
$start = $mid+1;
return binary_search($nums,$num,$start,$end);
}elseif($midNum == $num){
return $mid;
}
}