一、PHP7源码安装和Swoole源码编译安装
转载自:https://cloud.tencent.com/developer/article/1435062
一、PHP7源码安装和Swoole源码编译安装
1.1 PHP7源码安装
1.1.1 获取源码与安装
获取PHP7源码:www.php.net
tar -xzvf ... # 解压命令
./configure --prefix=/home/study/php # 安装至某个路径,提前安装gcc等
make # 编译
make install # 安装
源码执行文件放在:`bin`目录下
php -m # 查看 PHP 安装的扩展
1.1.2 简化PHP执行命令
alias
命令=命令的绝对路径
vim /.bash_profile
alias php=/home/work/soft/php/bin/php # 添加
source /.bash_profile # 注意
source FileName
作用:在当前bash
环境下读取并执行FileName
中的命令。 用于重新执行刚修改的初始化文档,如 .bash_profile
和 .profile
等等
注:该命令通常用命令“.
”来替代
如:source /etc/profile
与 . /etc/profile
是等效的
php -i | grep php.ini # 查找PHP的配置文件
1.2 Swoole源码编译安装
获取swoole源码:https://gitee.com/swoole/swoole.git
phpize
是用来扩展php
模块的,通过phpize
可以建立php
的外挂模块,解决没有configure
问题
/usr/local/php/bin/phpize # 在需要执行的目录执行这行代码即可
./configure --with-php-config=/usr/local/php/bin/php-config
make
make install
最后可以在`PHP`的扩展目录中看见`swoole.so` 扩展文件
1.3 双剑合璧,PHP7支持swoole
在`php.ini`文件中添加:`extension=swoole.so`
查看是否添加成功:`php -m`
在`swoole/examples/server`下执行`php echo.php`
查看是否执行端口:`9501`
netstat -anp|grep 9501
二、玩转网络通信引擎(非常重要
)
2.1 TCP服务&TCP客户端
2.1.1 TCP服务
Swoole官网文档:创建TCP服务器 | 创建UDP服务器
//创建Server对象,监听 127.0.0.1:9501端口
$serv = new swoole_server("127.0.0.1", 9501);
//swoole_server->set函数用于设置swoole_server运行时的各项参数
$serv->set([
'worker_num' => 6 , // worker进程数,cpu 1-4倍
'max_request' => 10000,
]);
/**
* 监听连接进入事件
* $fd 客户端连接的唯一标示
* $reactor_id 线程id
*/
$serv->on('connect', function ($serv, $fd, $reactor_id) {
echo "Client: {$reactor_id} - {$fd}-Connect.\n";
});
/**
* 监听数据接收事件
* $reactor_id = $from_id
*/
$serv->on('receive', function ($serv, $fd, $reactor_id, $data) {
$serv->send($fd, "Server: {$reactor_id} - {$fd}".$data);
});
//监听连接关闭事件
$serv->on('close', function ($serv, $fd) {
echo "Client: Close.\n";
});
//启动服务器
$serv->start();
测试**tcp
**服务器方法:
netstat -anp | grep 9501
- 通过
telnet
方式登录远程主机:telnet 127.0.0.1 9501
tcp
客户端脚本
查看当前**worker
**进程数:ps -aft | grep tcp_server.php
Tips:为了保证程序执行的完整性,当修改tcp
服务器脚本后最好设置平滑重启worker
进程
2.1.2 TCP客户端
阿里云服务器巨坑----端口未对外打开!!!websocket连接不上服务器,提示Provisional headers are shown
<?php
// 连接 swoole tcp 服务
$client = new swoole_client(SWOOLE_SOCK_TCP);
if(!$client->connect("127.0.0.1", 9501)) {
echo "连接失败";
exit;
}
// php cli常量
fwrite(STDOUT, "请输入消息:");
$msg = trim(fgets(STDIN));
// 发送消息给 tcp server服务器
$client->send($msg);
// 接受来自server 的数据
$result = $client->recv();
echo $result;
2.2 HTTP服务(常用
)
$http = new swoole_http_server("0.0.0.0", 8811);
//添加测试一:获取参数并打印出来
//$http->on('request', function ($request, $response) {
// $response->cookie("singwa",'xsssss', time() + 1800);
// $response->end('sss'.json_encode($request->get));
//});
/**
* https://wiki.swoole.com/wiki/page/783.html
* 配置静态文件根目录,与enable_static_handler配合使用。
* 设置document_root并设置enable_static_handler为true后,
* 底层收到Http请求会先判断document_root路径下是否存在此文件,
* 如果存在会直接发送文件内容给客户端,不再触发onRequest回调。
*/
$http->set(
[
'enable_static_handler' => true,
'document_root' => "/home/work/hdtocs/swoole_mooc/data",
]
);
$http->on('request', function($request, $response) {
//print_r($request->get);
$content = [
'date:' => date("Ymd H:i:s"),
'get:' => $request->get,
'post:' => $request->post,
'header:' => $request->header,
];
swoole_async_writefile(__DIR__."/access.log", json_encode($content).PHP_EOL, function($filename){
// todo
}, FILE_APPEND);
$response->cookie("singwa", "xsssss", time() + 1800);
$response->end("sss". json_encode($request->get));
});
$http->start();
2.3 WebSocket服务(重点)
2.3.1 基本概述
WebSocket
协议是基于TCP
的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex
)通信--允许服务器主动发送信息给客户端
为什么需要WebSocket
- 缺陷:
HTTP
的通信只能由客户端发起
WebSocket特点
- 建立在
TCP
协议之上 - 性能开销小通信高效
- 客户端可以与任意服务器通信
- 协议标识符
ws
wss
- 持久化网络通信协议
2.3.2 案例实现
2.3.2.1 服务端实现
1. 面向过程:
**procedure_ws_server.php**
$server = new swoole_websocket_server("0.0.0.0", 9912);
//配置静态文件根目录,可选
$server->set(
[
'enable_static_handler' => true,
'document_root' => "/home/wwwroot/www.lingyuan88.com/public/swoole/data",
]
);
//监听websocket连接打开事件
$server->on('open', 'onOpen');
function onOpen($server, $request) {
print_r($request->fd);
}
// 监听ws消息事件
$server->on('message', function (swoole_websocket_server $server, $frame) {
echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
$server->push($frame->fd, "singwa-push-secesss");
});
$server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
});
$server->start();
2. WebSocket服务优化,基础类库**面向对象:
**object_ws_server.php
class Ws {
CONST HOST = "0.0.0.0";
CONST PORT = 9912;
public $ws = null;
public function __construct() {
$this->ws = new swoole_websocket_server(self::HOST, self::PORT);
//配置静态文件根目录,可选
$this->ws->set(
[
'enable_static_handler' => true,
'document_root' => "/home/wwwroot/www.lingyuan88.com/public/swoole/data",
]
);
$this->ws->on("open", [$this, 'onOpen']);
$this->ws->on("message", [$this, 'onMessage']);
$this->ws->on("close", [$this, 'onClose']);
$this->ws->start();
}
/**
* 监听ws连接事件
* @param $ws
* @param $request
*/
public function onOpen($ws, $request) {
print_r($request->fd);
}
/**
* 监听ws消息事件
* @param $ws
* @param $frame
*/
public function onMessage($ws, $frame) {
echo "ser-push-message:{$frame->data}\n";
$ws->push($frame->fd, "server-push:".date("Y-m-d H:i:s"));
}
/**
* close
* @param $ws
* @param $fd
*/
public function onClose($ws, $fd) {
echo "clientid:{$fd}\n";
}
}
$obj = new Ws();
2.3.2.2 客户端实现
ws_client.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>singwa-swoole-ws测试</h1>
<script>
var wsUrl = "ws://120.77.206.215:9912";
var websocket = new WebSocket(wsUrl);
//实例对象的onopen属性
websocket.onopen = function(evt) {
websocket.send("hello-sinwa");
console.log("conected-swoole-success");
}
// 实例化 onmessage
websocket.onmessage = function(evt) {
console.log("ws-server-return-data:" + evt.data);
}
//onclose
websocket.onclose = function(evt) {
console.log("close");
}
//onerror
websocket.onerror = function(evt, e) {
console.log("error:" + evt.data);
}
</script>
</body>
</html>
2.3.2.3 测试
1. 通过**WebSocket
**静态文件目录测试
2. 通过**HTTP
**服务测试
2.4 异步Task任务使用(重点)
使用场景
- 执行耗时的操作(发送邮件 广播等)
注意:
- 投递异步任务之后程序会**
继续往下执行
**,不会等待任务执行完后再继续向下执行
class Ws {
CONST HOST = "0.0.0.0";
CONST PORT = 9912;
public $ws = null;
public function __construct() {
$this->ws = new swoole_websocket_server(self::HOST, self::PORT);
$this->ws->set(
[
'worker_num' => 2,
'task_worker_num' => 2,
]
);
//注册Server的事件回调函数
$this->ws->on("open", [$this, 'onOpen']);
$this->ws->on("message", [$this, 'onMessage']);
$this->ws->on("task", [$this, 'onTask']);
$this->ws->on("finish", [$this, 'onFinish']);
$this->ws->on("close", [$this, 'onClose']);
$this->ws->start();
}
/**
* 监听ws连接事件
* @param $ws
* @param $request
*/
public function onOpen($ws, $request) {
var_dump($request->fd);
}
/**
* 监听ws消息事件
* @param $ws
* @param $frame
*/
public function onMessage($ws, $frame) {
echo "ser-push-message:{$frame->data}\n";
// todo 10s
$data = [
'task' => 1,
'fd' => $frame->fd,
];
//投递异步任务
//注意:程序会继续往下执行,不会等待任务执行完后再继续向下执行
$ws->task($data);
//客户端会马上收到以下信息
$ws->push($frame->fd, "server-push:".date("Y-m-d H:i:s"));
}
/**
* @param $serv
* @param $taskId
* @param $workerId
* @param $data
* @return string
*/
public function onTask($serv, $taskId, $workerId, $data) {
print_r($data);
// 耗时场景 10s
sleep(10);
return "on task finish"; // 告诉worker,并返回给onFinish的$data
}