swoole学习笔记
TCP服务器
tcp.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$serv = new Swoole\Server("127.0.0.1",9501);
$serv->set([
'worker_num'=>8,//worker进程数(ps aft |grep tcp.php可查看到)
"max_request"=>10000,
]);
//监听连接事件
$serv->on('connect',function($serv, $fd, $reactor_id){
echo "client :{$reactor_id}-{$fd}-connect.\n";
});
//监听数据接收事件
$serv->on("receive",function($serv, $fd, $from_id, $data){
$serv->send($fd,"Server: {$from_id}-{$fd}-{$data}");
});
//监听连接关闭事件
$serv->on("close",function($serv,$fd){
echo "client: Close.\n";
});
//启动服务器
$serv->start();
终端测试:1
2
3
4 开启
php tcp.php
另开一个终端连接测试(可发送数据)
telnet 127.0.0.1 9501
TCP客户端
tcp_client.php(替代上一步telnet)1
2
3
4
5
6
7
8
9
10
11
12
13
14
$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;
终端测试:1
2
3
4 先打开tcp服务器
php tcp.php
另开一个终端打开tcp客户端连接测试
php tcp_client.php
UDP服务器
UDP服务器与TCP服务器不同,UDP没有连接的概念。启动Server后,客户端无需Connect,直接可以向Server监听的9502端口发送数据包。1
2
3
4
5
6
7
8
9
10udp.php
$serv = new Swoole\server("127.0.0.1",9502,SWOOLE_PROCESS,SWOOLE_SOCK_UDP);
$serv->on('Packet', function ($serv, $data, $clientInfo) {
$serv->sendto($clientInfo['address'], $clientInfo['port'], "Server ".$data);
var_dump($clientInfo);
});
$serv->start();
终端测试:1
2
3
4
5
6 启动udp服务器
php udp.php
用nc命令进行连接测试(安装:yum install -y nc)
nc -u 127.0.0.1 9502
hello
Server hello
UDP客户端
udp_client.php1
2
3
4
5
6
7
8
9
$client = new Swoole\client(SWOOLE_SOCK_UDP);
fwrite(STDOUT,"请输入消息:");
$msg = trim(fgets(STDIN));
$client->sendto('127.0.0.1',9502,$msg);
$result = $client->recv();
echo $result;
终端测试:1
2
3
4 启动udp服务器
php udp.php
打开另一终端连接测试
php udp_client.php
HTTP服务器
与php内置服务器差不到的原理,不走php-fpm
ws_server.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$http = new Swoole\Http\Server("0.0.0.0",8811);
//可设置静态文件
//底层收到Http请求会先判断document_root路径下是否存在此文件,如果存在会直接发送文件内容给客户端,不再触发onRequest回调
$http->set(
[
'enable_static_handler'=>true,
'document_root'=>"/vagrant_data/study/swoole/data",//静态文件根目录
]
);
$http->on("request",function($request, $response){
//获取请求的GET参数
print_r($request->get);
//可设置cookie,与PHP的setcookie一样
$response->cookie('name','cynickimi',time()+1800);
//向客户端浏览器发送HTML内容,string
$response->end('GET:'.json_encode($request->get));
});
$http->start();
WebSocket服务器
. 服务端
- WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信—允许服务器主动发送信息给客户端。
- 协议标识符
ws
wss
1 |
|
.客户端
ws_client.html(位置:websocket设置的document_root)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<script>
var wsUrl = "ws://192.168.1.10:8812";
var websocket = new WebSocket(wsUrl);
websocket.onopen = function(evt){
websocket.send("hello,i am client.");
console.log("connect-swoole-success.");
}
websocket.onmessage = function (evt) {
console.log('ws-server-return-data:'+evt.data);
}
websocket.onclose = function(evt){
console.log("close");
}
websocket.onerror = function (evt, e){
console.log("error:" + evt.data);
}
</script>
.运行测试1
2
3
4 启动websocket服务端
php ws_server.php
浏览器访问客户端
http://192.168.1.10:8812/ws_client.html
Task任务(异步)
ws.php(面向对象风格)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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class Ws{
CONST HOST = "0.0.0.0";
CONST PORT = 8812;
public $ws = null;
public function __construct()
{
$this->ws = new Swoole\WebSocket\Server("0.0.0.0", 8812);
$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();
}
public function onOpen($ws,$request)
{
var_dump($request->fd);
}
public function onMessage($ws,$frame)
{
echo "ser-push-message:{$frame->data}\n";
$data = [
'task'=>1,
"fd"=>$frame->fd,
];
$ws->task($data);//出发onTask,异步
$ws->push($frame->fd,"server-push:".date("Y-m-d H:i:s"));
}
public function onTask($serv,$taskId,$workId,$data)
{
print_r($data);
//耗时场景
sleep(10);
return "on task finish.";//告诉worker
}
/**
* @param $serv
* @param $taskId
* @param $data onTask函数return的内容
*/
public function onFinish($serv, $taskId, $data)
{
echo "taskID:{$taskId}\n";
echo "finish-data-success:{$data}.\n";
}
public function onClose($ws,$fd)
{
echo "clientid:{$fd}";
}
}
$obj = new Ws();
测试:1
2
3
4
5 websocket服务端
php ws.php
启动websocket客户端
php http_server.php
http://192.168.1.10:8811/ws_client.php
异步文件系统IO
4.3.0之后的版本用协程代替(coroutine)
读取文件
1 |
|
写入文件
1 |
|
异步MySQL
Swoole\MySQL已内置到Swoole中,无需通过–enable-async-mysql编译参数开启
1 |
|
进程
process.php1
2
3
4
5
6
7
$process = new swoole_process(function(swoole_process $pro){
$pro->exec("/usr/local/php7.2/bin/php",[__DIR__."/../server/http_server.php"]);
}, false);
$pid = $process->start();//创建子进程
echo $pid.PHP_EOL;//子进程pid
swoole_process::wait();//回收结束运行的子进程。
测试:
运行process.php,会打印出子进程id,即是创建的http_server进程的id
查看process.php的进程号
查看process.php(4124)进程下的所有进程关系:
查看http_server.php的进程关系:
使用场景:模拟读取4个url,每个耗时1s,一般顺序执行需要4s1
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
echo "process-start-time:".date("Ymd H:i:s").PHP_EOL;
$workers = [];
$curl = [
'https://www.baidu.com',
'https://www.taobao.com',
'https://www.php.net/',
'https://wiki.swoole.com',
];
function curlData($url){
//模拟读取耗时场景
sleep(1);
return 'read'.$url." success.".PHP_EOL;
}
for($i = 0; $i<4; $i++){
$process = new Swoole\Process(function(Swoole\Process $worker) use($i,$curl){
$content = curlData($curl[$i]);
echo $content.PHP_EOL;
},true);
$pid = $process->start();
$workers[$pid] = $process;
}
foreach($workers as $process){
echo $process->read();//从管道中读取数据。
}
echo "process-end-time:".date("Ymd H:i:s").PHP_EOL;
执行结果:1s就执行结束
内存表
使用场景:可用于数据共享。觉得有点类似redis1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//创建内存表
$table = new swoole_table(1024);
$table->column('id', $table::TYPE_INT, 4);
$table->column('name',$table::TYPE_STRING, 64);
$table->column('age', $table::TYPE_INT, 3);
$table->create();
//新增内容
$table->set('cynickimi',['id'=>1,'name'=>'cynickimi','age'=>24]);
//另一种新增内容方法
$table['cynickimi2']=[
'id'=>2,
'name'=>'cynickimi2',
'age'=>24,
];
//两种获取数据的方法
print_r($table->get('cynickimi'));
print_r($table['cynickimi']);
//自增
$table->incr('cynickimi2','age',2);
print_r($table['cynickimi2']);
//执行完释放内存,可用于共享数据
协程
协程MySQL
1 |
|
测试:1
2php mysql.php
curl 127.0.0.1:8811
协程Redis
1 |
|
测试:1
2
3php redis.php
获取redis中key为name的值
curl 127.0.0.1:8811?key=name
- 本文链接:https://cynickimi.github.io/2019/06/24/swoole/
- 版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。