Socket通信编程

##Socket连接过程

  • 服务器监听:服务端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
  • 客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此客户端的套接字必须首先描述它所要连接的服务器的套接字,并给出服务器端的套接字的地址和端口号,然后向服务器端提出连接请求。
  • 连接确认:当服务器端套接字监听或者接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端的套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接受其他客户端套接字的连接请求。

PHP安全

XSS防御
  1. 转义/编码 htmlspecialchars()
  2. 过滤 strip_tags
  3. CSP(Content Security Policy)
  4. 第三方库
    • HTML purifier
    • htmLawed
    • Zend_Filter_Input
会话攻击防御
  • session_regenerate_id()
  • 二级令牌
  • 检测UA和用户IP

PHP异步并行

一个PHP Web程序的执行过程

  1. 请求开始 (GET/Post/Cookie/Session)
  2. Mysql数据库查询/Redis查询
  3. 模板渲染输出HTML/json_encode
  4. 请求结束(回收所有内存和资源)

PHP-FPM进程的完整流程

  1. 请求1 处理请求 发送响应
  2. 请求2 处理请求 发送响应
  3. 请求3 处理请求 发送响应
  4. 。。。。

Accept->Recv(处理)->Send->Close->Accept->Recv->Send->Close

多进程并发地处理请求

  • 进程1 请求1->请求2->……->请求N
  • 进程2
  • 进程3
  • 进程N

扩展

  1. stream
  2. sockets
  3. libevent/event
  4. pcntl/posix
  5. pthread
  6. sysvsem/sysvmsg
  7. shmop/sysvshm

PHP同步阻塞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$serv = stream_socket_server("tcp://0.0.0.0:8000",$errno,$errstr) or die ("服务创建失败");

for ($i=0; $i<32 ;$i++) {
if (pcntl_fork() == 0) {
while(1) {
$conn = stream_socket_accept($serv);
$request = fread($conn);
$response = "Hello 异步并行";
fwrite($response);
fclose($conn);
}
exit(0);
}
}

Vagrant使用

Vagrant常用命令

  1. vagrant box list 查看目前已有的box
  2. vagrant box add 新增一个box
  3. vagrant box remove 删除指定的box
  4. vagrant init 初始化配置vagrantfile
  5. vagrant up 启动虚拟机
  6. vagrant ssh ssh登录虚拟机
  7. vagrant suspend 挂起虚拟机
  8. vagrant reload 重启虚拟机
  9. vagrant half 关闭虚拟机
  10. vagrant status 查看虚拟机状态
  11. vagrant destroy 删除虚拟机

对虚拟机的优化

替换源

  • sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak #备份源文件
  • sudo vim /etc/apt/source.list #修改源
  • sudo apt-get update #更新列表
  • 源内容如下:
1
2
3
4
5
6
7
8
9
10
deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse

安装Apache Nginx PHP

sudo apt-get install 对应名称
对应名称 -v 可以查看版本号

Apache更改端口,将端口设置为8888

  1. 修改 ports.conf 文件
  2. curl -I ‘http://127.0.0.1:8888'

Mysql 安装

  1. sudo apt-get install mysql-server #服务器端
  2. 安装期间会提示输入为mysql设置root密码,我这边不操作,直接enter 不设置密码
  3. sudo apt-get install mysql-client #客户端
  4. mysql -uroot -p #测试连接库,上面安装服务端没有设置密码,这里直接enter进入

php扩展 sudo apt-get install 名称

  1. php5-mcrypt
  2. php5-mysql
  3. php5-gd

支持apache2的php

  1. sudo apt-get install libapache2-mod-php5
  2. 开启rewrite功能
  3. sudo a2enmod rewrite

    支持nginx fastcgi

  4. sudo apt-get install php5-cgi php5-fpm

修改成9000端口 ,默认sock模式

  1. cd /etc/php5/fpm/pool.d
  2. sudo vim www.conf # search listen = 127.0.0.1:9000
  3. sudo /etc/init.d/php5-fpm restart

##Vagrant高级知识

  1. 端口转发 config.vm.network "forwarded_port", guest: 8888, host: 8889
  2. 共享文件夹config.vm.synced_folder "/Users/ps/www","/home/www",:nfs=>true
  3. 私有网络设置 config.vm.network "private_network", ip: "192.168.33.10"

虚拟机优化

  1. 虚拟机名称 vb.name = "ubuntu_ps"
  2. 虚拟机主机名 config.vm.hostname = "ps"
  3. 配置虚拟机内存和CPU
    • vb.memory = "1024"
    • vb.cpus = 2

打包分发

1.打包
vagrant package –output xxx.box
vagrant package –output xxx.box –base 虚拟机名称

设计模式之装饰器模式

文章类获取初始的文章内容

1
2
3
4
5
6
7
8
9
10
11
12
13
class Art
{
protected $content = null;

public function __construct($content) {
$this->content = $content;
}

public function decorator() {
return $this->content;
}
}

定义装饰文章类
art 参数 保存着 文章类的初始化对象

1
2
3
4
5
6
7
8
9
10
11
12
13
class ArtDesc extends Art
{
protected $art = null;

public function __construct($art)
{
$this->art = $art;
}

public function decorator() {

}
}

SEO类和AD类继承装饰器类达到对文章内容的添加的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
class SeoArt extends ArtDesc
{
public function decorator()
{
return $this->art->decorator().'SEO KEYWORDS';
}
}

class AdArt extends ArtDesc {
public function decorator() {
return $this->art->decorator().'广告内容';
}
}

调用
将初始化文章基础对象 传入装饰器类

1
2
3
4
$art = new Art('文章内容');
$art = new SeoArt($art);
$art = new AdArt($art);
echo $art->decorator();

设计模式之策略模式

设计模式之策略模式


  • 面向对象中有什么比是什么更灵活
  • 组合比继承更灵活
  • 饭店和厨师的关系 是 一对多
  • 比如新开饭店 如果单纯的复制饭店 这样不能会造成很多浪费的方法 但是如果以饭店拥有厨师的方式处理 那么 饭店的样式可以随机变换,因此首先声明一个饭店类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class FD
{
protected $tangCreator = null;
protected $caiCreator = null;
protected $fanCreator = null;

public function __construct($f,$c,$t) {
$this->fanCreator = $f;
$this->tangCreator = $t;
$this->caiCreator = $c;
}

public function createFan() {
return $this->fanCreator->fan();
}

public function createCai() {
return $this->caiCreator->cai();
}

public function createTang() {
return $this->tangCreator->tang();
}
}

再声明厨师类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class SouthDinner {
public function fan() {
return '米饭';
}

public function cai() {
return '甜食';
}

public function tang() {
return '蛋花汤';
}
}

class NorthDinner {
public function fan() {
return '馒头';
}

public function cai() {
return '炒菜';
}

public function tang() {
return '粥';
}
}

最后调用

1
2
3
4
$fd = new FD(new SouthDinner(),new NorthDinner(),new SouthDinner());

echo $fd->createCai(),'<br>';
echo $fd->createTang(),'<br>';

“设计模式之责任链”

设计模式之责任链


定义子类
首先定义三个类,要声明power权值,以power来判断是否有权利去操作,传过来的数据,还需要声明上一级,责任链模式,要有层级关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Banzhu extends Admin
{
protected $power = 1;
protected $top = 'Police';

public function doProc() {
echo '删帖';
}
}

class Police extends Admin
{
protected $power = 2;
protected $top = 'Guoan';

public function doProc() {
echo '抓人';
}
}

class Guoan extends Admin
{
protected $power = 3;
protected $top = null;

public function doProc() {
echo '灭口';
}
}

定义父类
子类均要继承父类方法Admin,Admin的__construct构造方法中,首先判断该类的上一级是否为空,如果是,那么该类是这个责任链中的顶级。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Admin
{
public function __construct() {
if ($this->top == null) {
return;
}
$this->toper = new $this->top();
}

public function proc($danger) {
if($danger <= $this->power) {
$this->doProc();
} else {
$this->toper->proc($danger);
}
}
}

调用
实例化最底层类,然后调用方法传入power

$obj = new Banzhu();
$obj->proc(3);

“设计模式之工厂模式 抽象工厂”

设计模式之工厂模式 抽象工厂

多个类具有相同的属性和方法

1.首先声明类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Mysql
{

}

class Sqlite
{

}

class MyPdo
{

}

2.建立一个工厂类接口,工厂类中可以声明属性和方法

1
2
3
4
5
interface Factory {

public static function getDB();

}

3.然后声明抽象工厂类 实现工厂类接口中的静态方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class MysqlFactory implements Factory
{
public static function getDB() {
return new Mysql();
}
}

class MyPdoFactory implements Factory
{
public static function getDB()
{
// TODO: Implement getDB() method.
return new MyPdo();
}
}

class MysqlliteFactory implements Factory
{
public static function getDB()
{
// TODO: Implement getDB() method.
return new Sqlite();
}
}

4、最后调用工厂类中的静态方法

1
2
3
$factory = 'MysqlFactory';
$db = $factory::getDB();
print_r($db);

“JS设计模式之观察者模式”

设计模式之观察者模式


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<script>
var sel =document.getElementById('sel');
sel.observes =[];
sel.attach =function (obj) {
sel.observes[sel.observes.length] = obj;
};

sel.detach = function (obj) {
for( var i=0; i < sel.observes.length; i++) {
if(this.observes[i] == obj) {
delete this.observes[i];
}
}
};

sel.onchange = sel.notify =function () {
for( var i=0; i < sel.observes.length; i++) {
//
this.observes[i].update(this);
}
};
var test2 = document.getElementById('test2');
var test3 = document.getElementById('test3');
test3.update = function (sel) {
if(sel.value == '1'){
this.innerHTML = '2';
} else if(sel.value == '0') {
this.innerHTML ='a';
}
};
test2.update = function (sel) {
if(sel.value == '1'){
this.innerHTML = '1';
} else if(sel.value == '0') {
this.innerHTML ='s';
}
};

sel.attach(test2);
sel.attach(test3);
</script>

mysql主从复制

mysql主从复制


一、 配置主服务器

  1. 编辑my.cnf文件 默认位置一般在/etc下

在[mysqld]的下面加入下面代码:

1
2
3
4
5
6
log-bin=mysql-bin
server-id=1
innodb_flush_log_at_trx_commit=1
sync_binlog=1
binlog-do-db=wordpress//表明备份哪个数据库
binlog_ignore_db=mysql //表明忽略mysql库的备份

2.重启mysql

1
service mysqld restart

3.连接mysql数据库

1
mysql -u root -p

4.在主服务器上创建用户并赋予”REPLICATION SLAVE”权限 x.x.x.x为 从属服务器ip

  • 已授权的方式创建用户
1
2
3
4
GRANT REPLICATION SLAVE
-> ON *.*
-> TO 'ps'@'192.168.199.118'
-> IDENTIFIED BY '123456';

5.执行以下命令锁定数据库以防止写入数据。

1
mysql>FLUSH TABLES WITH READ LOCK;

6.导出数据库备份文件

1
2
3
mysqldump -u root -p  --databases work  --lock-tables=false > all.sql
//lock-tables 是否锁定数据表
//databases 数据库名

7.用scp命令传输数据库文件all.sql到从服务器

1
scp all.sql root@192.168.199.118:/root
  • [注意:] scp命令使用时 主服务器和从服务器都要安装 openssh-clients
1
2
yum install -y openssh-clients
ssh -v //查看服务器上是否有openssh-clients

8.连接mysql数据库 进入mysql命令行查看master状态

1
2
3
4
5
6
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 260 | work | mysql |
+------------------+----------+--------------+------------------+

9.解锁数据表

1
mysql> UNLOCK TABLES;

二、 配置从属数据库

1.导入主数据库数据表

1
mysql -u root -p work < all.sql
  • [注释] < 导入 > 导出

2.编辑my.cnf,在[mysqld]下面加入

server-id=2

可以自己定义,保证唯一

3.登录mysql服务器,执行以下命令。

1
2
3
4
5
6
7
8
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.199.163',
-> MASTER_USER='ps',
-> MASTER_PASSWORD='123456',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=260,
-> MASTER_CONNECT_RETRY=10;
  • [注意:] MASTER_HOST:主服务器的IP。
  • MASTER_HOST:主服务器的IP。
  • MASTER_USER:配置主服务器时建立的用户名
  • MASTER_PASSWORD:用户密码
  • MASTER_PORT:主服务器mysql端口,如果未曾修改,默认即可。

4.启动slave进程。

1
2
START SLAVE;//开启SLAVE进程
show slave status\G //查看SLAVE进程状态
  • [注意]连接不上mysql数据库 有可能是防火墙的原因
1
service iptables stop

“单例模式”

设计模式之单例模式


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
class Single
{
protected $rnd;
protected static $ins =null ;

//将自动加载 设置为 protected类型
//这样没法new 类名进行实例化
protected function __construct() {
$this->rnd =rand(0,1000);
}

//声明一个静态方法
public static function getins(){
//判断self::$ins 保存着实例化之后的对象
if (self::$ins == null) {
self::$ins = new self();
}

return self::$ins;
}


}
?>