1.安装swoole扩展 具体查看 swoole安装步骤
2.看相关swoole文档 实现tcp服务
代码
tcp.php
<?php
/**
* User: may
* Date: 2019/6/4
* Time: 下午2:52
*/
//创建server对象 监听127.0.0.1
$serv=new swoole_server("127.0.0.1","9501");
$serv->set([
'reactor_num' => 111, //reactor thread num
'worker_num' => 8, //worker process num 进程数 建议等于开启cpu核数的1-4倍
'max_request' => 10000, //每个进程处理的最大用户数
]);
//监听进入事件
$serv->on('connect',function ($serv,$fd,$reactor_id){
echo "Client:{$reactor_id}-{$fd}Connet!!.\n";
});
//监听数据接收事件
/**
* $fd客户端链接的唯一标识
*/
$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();
3.测试
打开终端
执行 php tcp.php
使用 netstat -an|grep 9501 命令
查看9501端口服务是否开启
开启新终端
执行 客户端连接到服务 telnet 127.0.0.1 9501
多开启几个客户端连接到服务端
关闭服务端
客户端也随之关闭
启动一个http_server服务 并测试
http_server.php
例子3 通过http_server请求html页面
<?php
/**
* User: may
* Date: 2019/6/5
* Time: 上午11:18
*/
$http = new swoole_http_server("0.0.0.0", 8811);//0.0.0.0表示监听所有地址
$http->set(
[
'enable_static_handler'=>true,
'document_root'=>"/Applications/MAMP/htdocs/swoole_code/data/", //html文件目录
]);
$http->on('request', function ($request, $response) {
print_r($request->get);
$response->cookie("admin_name","ssss",time()+1800);
$response->end("<h1>http server Data :</h1>".json_encode($request->get)); //数据要显示到浏览器 需要把数据放在end 方法
});
$http->start();
例子4 通过http_server.php 启动服务
ws_server.php 推送消息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ws_client测试</title>
</head>
<body>
<h1>hill ws测试</h1>
<script>
var wsUrl = 'ws://127.0.0.1:8813';
var websocket = new WebSocket(wsUrl);
//实例对象onopen属性
websocket.onopen = function (evt) {
websocket.send('hello hill');
console.log("conneted success ");
}
//实例化 onmessage
websocket.onmessage = function (evt) {
console.log("ws-sever-return-data is : " + evt.data);
}
//onclose
websocket.onclose=function (evt) {
console.log("cloese");
}
//onerror
websocket.onerror=function (evt,e) {
console.log("error:"+evt.data);
}
</script>
</body>
</html>
ws_server.php
<?php
/**
* User: may
* Date: 2019/6/5
* Time: 下午2:15
*/
$server = new swoole_websocket_server ("0.0.0.0", 8813);
$server->set(
[
'enable_static_handler'=>true,
'document_root'=>"/Applications/MAMP/htdocs/swoole_code/data/",
]);
//监听websocket 连接打开事件
$server->on('open', 'onOpen');
function onOpen($server,$request){
print_r($request->fd);
}
//监听websocket 消息事件
/**$fd 客户端连接的ID,如果指定的$fd对应的TCP连接并非websocket客户端,将会发送失败
$data 要发送的数据内容
$opcode,指定发送数据内容的格式,默认为文本。发送二进制内容$opcode参数需要设置
* */
$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, "hello websocket server push success"); //把数据push到客户端
});
$server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
});
$server->start();
例子4.
task和push异步执行任务
<?php
/**
* User: may
* Date: 2019/6/5
* Time: 下午3:42
* ws 基础类库优化
*/
class ws
{
const HOST = "0.0.0.0";
const PORT = 8813;
public $ws = null;
public function __construct()
{
$this->ws = new swoole_websocket_server ("127.0.0.1", 8813);
$this->ws->set([
'worker_num'=>2,
'task_worker_num'=>2,
]);
$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 "sever-push-message:{$frame->data}\n";//来自客户端发的数据
//todo 10s
$data = [
'task' => 1,
'fd' => $frame->fd,
];
$ws->task($data);//本来应该先执行task 在执行push 但是 异步操作 所以push不必等task执行完再执行 而是同步进行 所以很快
$ws->push($frame->fd, "server-push:" . "sever data 2019");//server推送数据给客户端
}
/**
* @param $serv
* @param $taskId
* @param $workerId
* @param $data
*/
public function onTask($ws, $taskId, $workerId, $data)
{
echo "Tasker进程接收到数据\n";
print_r($data);
//耗时场景10s
sleep(10);
return " on task finish";
}
/**
* @param $serv
* @param $taskId
* @param $data onTask方法return的值
*/
public function onFinish($ws, $taskId, $data)
{
echo "taskId:{$taskId}\n";
echo "finish-data-success:{$data}\n";
}
/**
*
* @param $ws
* @param $fd
*/
public function onClose($ws, $fd)
{
echo "closed client_id:{$fd}\n";
}
}
$obj = new ws();
终端在相关目录执行
php http_server
php ws.php
浏览器打开 http://127.0.0.1:8811/ws_client.html
代码中应该先执行task 再执行push task要停留10s 但是客户端收到push的消息很快远小于10s
这就是异步处理机制
多进程执行
<?php
/**
* User: may
* Date: 2019/6/14
* Time: 下午5:24
*/
echo "process-start-time" . date('Y-m-d H:i:s', time()) . PHP_EOL;
$wokers = [];
$urls = [
'http://baidu.com',
'http://wiki.swoole.com',
'http://qq.com',
'http://sina.com',
'https://www.jd.com',
'https://www.taobao.com'
];
//传统php 做法
//foreach ($urls as $url) {
// $contents[] = file_get_contents($urls);
//}
//并不是 耗时6秒 而是1秒 6个进程同时进行
for ($i = 0; $i < 6; $i++) {
$process = new swoole_process(function (swoole_process $worker) use ($i, $url) {
$content = curlData($url[$i]);
echo $content . PHP_EOL;
// $worker->write($content);
}, true); //true 就到管道 false到屏幕
$pid = $process->start();
$wokers[$pid] = $process;
}
foreach ($wokers as $process) {
echo $process->read();
}
//获取url里面内容
function curlData($url)
{
//file_get_contents();
sleep(1);
return $url . "sucess" . PHP_EOL;
}
echo "process-end-time" . date('Y-m-d H:i:s', time()) . PHP_EOL;