概念篇
协议部分
1. TCP/UDP区别
TCP
- TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议
- TCP面向连接,提供可靠地数据服务
- TCP首部开销20字节
- TCP逻辑通信信道是全双工的可靠信道
- TCP连接只能是点到点的
UDP
- UDP是参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠的信息传递服务
- UDP无连接,不可靠
- UDP首部开销8字节
- UDP逻辑通信信道是不可靠信道
- UDP没有拥塞机制,因此网络出现拥堵不会使源主机的发送效率降低
- UDP支持一对一,多对一,多对多的交互通信
2. 长连接与短连接
短连接
- client向server发起请求 (第一次握手)
- server接收到请求,建立连接 (第二次握手)
- client向server发送信息 (第三次握手)
- server回应client
- 一次读写完成,双方都可发起close操作关闭连接,一般为client发起close操作;
短连接一般只会在client和server间传递一次读写操作,短连接管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段
长连接
在短连接第一次请求结束后继续保持连接。
长连接可以省去较多的TCP建立和关闭操作,减少资源浪费,节省时间,对于比较频繁的请求资源的客户端比较适用于长连接
设计模式
1. 单例模式
当需要保证对象只有一个实例的时候,单例模式是非常有用的。他把创建对象的控制权交给一个单一的点上,任何时候应用程序都只会存在且仅存在一个实例。单例类不应该能在类的外部进行实例化。
一个单例类应该具备以下几个因素:
必须拥有一个访问级别为
private
的构造函数,用于阻止类被随意实例化必须拥有一个保存类的实例的静态变量
必须拥有一个访问这个实例的公共静态方法,该方法通常被命名为
getInstance()
必须拥有一个私有的空的
__clone()
方法,防止实例被克隆复制
2. 工厂模式
工厂模式是一种类,它具有为你创建对象的某些方法,你可以使用工厂类创建对象而不使用 new。这样,如果你想要更改所创建的对象类型只需要更改工厂即可,使用该工厂的所有代码会自动更改。
工厂模式往往配合接口一起使用,这样应用程序就不必要知道这些被实例化的类的具体细节,只要知道工厂返回的是支持某个接口的类就可以方便的使用了。
3. 观察者模式
缓存
1. Redis和Memcached的区别
Redis和Memcache都是将数据存放在内存中,都是内存数据库。但是Memcache还可以缓存其他东西,比如图片、视频
Redis不只支持简单的k/v类型的数据,同时还提供list、set、hash等数据结构的存储
虚拟内存,当物理内存用完时Redis可以将一些很久没有用到的value交换到磁盘
事务功能,Redis 提供了事务的功能,可以保证一系列命令的原子性
存储安全,memcache挂掉后,数据没了;redis可以定期保存在磁盘(持久化),参考:redis持久化的几种方式
灾难恢复,memcache挂掉后数据不可恢复;redis数据丢失后可以通过aof恢复
redis支持数据的备份,即master-slave模式的数据备份
应用场景不同:redis除了可以做nosql数据库之外,还能做消息队列、计数器、共享session等。memcache适合于缓存sql语句、数据集、用户临时性数据、延迟查询数据和session等
算法篇
排序算法
1. 快速排序
function quickSort($arr) {
//获取数组长度
$length = count($arr);
//判断长度是否要二分比较
if ($length <= 1) {
return $arr;
}
//定义基准元素
$base = $arr[0];
//定义两个空数组,存放和基准元素比较后的数组
$left = [];
$right = [];
//遍历数组
for ($i = 0; $i < $length; $i++) {
if($arr[$i] > $base) {
$right[] = $arr[$i];
} else {
$left[] = $arr[$i];
}
}
//递归处理left和right数组
$left = quickSort($left);
$right = quickSort($right);
//合并
return array_merge($left, [$base], $right);
}
2. 冒泡排序
思路:从数组的第1、2位数开始比较,把较大的数字向后排列,每一轮冒出最大的数;
核心:一个长度为N的数组,第 i 轮需要进行 N - i 次可以获得最大的数
function bubbleSort($arr) {
$length = count($arr);
$temp = 0;
//第一层控制冒泡轮数
for ($i = 0; $i < $length - 1; $i++) {
//内层循环控制从第0个键值与最后后一个键值比较,每次冒出一个最大的数)
for ($j = 0; $j < $length - 1 - $i; $j++) {
if ($arr[$j] > $arr[$j+1] ) {
$temp = $arr[$j];
$arr[$j+1] = $arr[$j];
$arr[$j] = $temp;
}
}
}
return $arr;
}
3. 二维数组的排序算法
function array_sort($arr, $keys, $order = 0) {
if (!is_array($arr)) {
return false;
}
//定义一个数组,保存排序键对应的值
$keysValue = [];
//遍历保存排序键的值
foreach($arr as $key => $val) {
$keysValue[$key] = $val[$keys];
}
//$order值为0,则按照低到高排序
if ($order == 0 ) {
asort($keysValue); //对数组单元从低到高进行排序并保持索引关系。
} else {
arsort($keysValue); //对数组单元从高到低进行排序并保持索引关系。
}
reset($keysValue); //将内部指针返回至第一个元素;
$newArray = [];
foreach ($keysValue as $key => $val) {
$newArray[$key] = $arr[$key];
}
return $newArray;
}
4. 遍历获取文件夹下的所有文件夹和文件
function my_scandir($dir){
$files = array();
if($handle = opendir($dir)) { //opendir() 打开指定文件夹,成功则返回目录句柄资源。失败则返回 FALSE。
while (($file = readdir($handle))!== false) { //readdir() 返回目录中下一个文件的文件名。
if($file != '..' && $file != '.') {
if(is_dir($dir."/".$file)){
//递归获取下一级文件夹
$files[$file]=my_scandir($dir."/".$file);
}else{
$files[] = $file;
}
}
}
closedir($handle);
return $files;
}
}
未完待续。。。。