page contents

swoole 第7次课 荷塘墨画:io复用与信号模型2

信号模型

4.理解信号

41)查看liinux信号 kill -l 

attachments-2020-12-uOvqvaM75fe82c9bec09e.jpg信号列表及意义:https://wiki.swoole.com/#/other/signal?id=linux-信号列表

attachments-2020-12-75WOvejg5fe8305b2f6d6.jpg


使用 kill      信号    主进程PID  如下,kill -10 11830 ,重启了workers

attachments-2020-12-2tFgSzBI5fe83b1c1a7e9.png

42)信号函数

pcntl_signal         安装信号https://php.golaravel.com/function.pcntl-signa.html

posix_kill                         绑定信号https://php.golaravel.com/function.posix-kill.html

pcntl_signal_dispatch         发送信号https://php.golaravel.com/function.pcntl-signa-dispatch.html

43)程序设置信号的流程

attachments-2020-12-pVCYJVLo5fe83225161e7.png

44)客户端Xshell等kill命令信号的流程

attachments-2020-12-Ff6cuGh55fe833bdb37e9.png

45)理解信号函数

attachments-2020-12-CoulH6K75fe86670b532d.png

小试牛刀

iostarjhy\test\signal\signal.php

<?php

function sig_handler($sig){
var_dump($sig);
echo "信号操作\n";
}

//绑定信号及触发方法(处理方法)
pcntl_signal(SIGIO,"sig_handler");
//SIGIO :描述符上可以进行 I/O 操作

//绑定进程和信号
posix_kill(posix_getpid(),SIGIO);

echo "kl\n";

//分发
pcntl_signal_dispatch();

运行

attachments-2020-12-JYXBVEed5fe866af3c915.png

5实现信号模型
基类 iostarjhy\src\WorkerBase.php ,同上,略
信号实现类iostarjhy\src\Signal\Worker.php
<?php
namespace IoStarJhy\Signal;

use IoStarJhy\WorkerBase;

class Worker extends WorkerBase {

public function accept()
{
//建立并挂起连接,可接受多次信息(而不是一次就关闭服务)
while(true){
//监听是否存在连接
$conn = stream_socket_accept($this->server);
if(!empty($conn)){
//触发建立连接事件
$this->events['connect']($this,$conn);
}
//绑定信号及触发方法(处理方法)
pcntl_signal(SIGIO,$this->sigHandler($conn));
//绑定进程和信号
posix_kill(posix_getpid(),SIGIO);
//分发
pcntl_signal_dispatch();
}
}

public function sigHandler($conn)
{
return function($sig) use($conn){
switch($sig){
case SIGIO;
$this->sendMessage($conn);
break;
}
};
}

public function sendMessage($conn)
{
//接收服务的信息
$data = fread($conn, 65535);
if($data === '' || false === $data){
$this->checkConn($data, $conn);
}else{
$this->events['receive']($this, $conn, $data);
}
}
//检验连接
protected function checkConn($buffer,$conn){
if(strlen($buffer) === 0){
if(! \get_resource_type($conn) == "Unknown"){
//断开连接
$this->close($conn);
}
call_user_func($this->events['close'],$this,$conn);
unset($this->sockets[(int) $conn]);
}
}
}
测试服务端 iostarjhy\test\signal\server.php
<?php
require_once __DIR__."/../../vendor/autoload.php";

use IoStarJhy\Signal\Worker;

$server = new Worker('0.0.0.0',9500);

$server->on('connect',function($server,$client){
dd($client,"客户端建立连接成功");
});
$server->on('receive',function(Worker $server,$client,$data){
dd($data,'处理客户端的数据');
$server->send($client,'hello client');
//$server->close($client);
});
$server->on('close',function(Worker $server,$client){
dd($client,'断开连接');
//$server->close($client);
});

$server->start();
测试客户端iostarjhy\test\signal\client.php
<?php
require_once __DIR__ . "/../../vendor/autoload.php";

//连接服务端
$fp = stream_socket_client("tcp://192.168.204.168:9500");

fwrite($fp, "hello server1");
dd(fread($fp, 65535));
运行结果
attachments-2020-12-GB5ZHs5y5fe86f9e813ed.png

至此,信号模型已实现通信了

说明:信号模型主要用于框架中服务的重启,重加载及不同进程间的通讯,而不是用于写模型的。

附:

问题:为什么阻塞模型不能进行两次通信?

attachments-2020-12-7BRWODyI5fe8712fe3595.jpg

receive后,进行下一轮,stream_socket_accept去监听新的连接了,上一个连接再发信息也没用了


  • 发表于 2020-12-26 17:40
  • 阅读 ( 716 )

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
吉洪叶
吉洪叶

21 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1320 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章