1首先我们写一个入口脚本,这里简单点的功能就是开启服务和关闭服务

<?php
//CLI命令
if(isset($argv[1]) && in_array($argv[1], ['start', 'restart', 'status', 'stop', 'reload']))define('CLI_COMMAND', $argv[1]);
else define('CLI_COMMAND', 'start');
define('ROOT',__DIR__);
define('TMP_PATH',ROOT.DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR);
define('APP_NAME','mySwoole');
require_once 'ServerCallFun.php';
Class Root
{static public $Ip  = '127.0.0.1';static public $port  = 9510;//swoole对象Static Public $serv = null;//进程对象Static Public $worker = null;/*** 主框架运行*/Static Public function run(){$command = 'Root::' . CLI_COMMAND;$command();}/*** 启动框架*/Static Private function start(){if(is_file(TMP_PATH . 'server.pid')){$pid = @file_get_contents(TMP_PATH . 'server.pid');if($pid && \swoole_process::kill($pid, 0))die("Framework has been started!" . PHP_EOL);}echo "Framework Starting...", PHP_EOL;date_default_timezone_set('Asia/Shanghai');$setup = ['pid_file' => TMP_PATH.'server.pid',//在Server启动时自动将master进程的PID写入到文件,在Server关闭时自动删除PID文件'reactor_num' => 4,//reactor_num建议设置为CPU核数的1-4倍'worker_num' => 4,'backlog' => 128,//Listen队列长度,如backlog => 128,此参数将决定最多同时有多少个等待accept的连接。'max_request' => 100,//设置worker进程的最大任务数,默认为0,一个worker进程在处理完超过此数值的任务后将自动退出,进程退出后会释放所有内存和资源。'dispatch_mode' =>3,//抢占模式,主进程会根据Worker的忙闲状态选择投递,只会投递给处于闲置状态的Worker'daemonize'=>true,'log_file' => TMP_PATH .'swoole.log',//开启守护进程模式后(daemonize => true),标准输出将会被重定向到log_file。在PHP代码中echo/var_dump/print等打印到屏幕的内容会写入到log_file文件日志标号
];self::$serv = new swoole_server(self::$Ip,self::$port) or die('Swoole Starting Failed!' . PHP_EOL);self::$serv->set($setup);self::$serv->on('start', 'ServerCallFun::start');//在主进程start后调用self::$serv->on('managerstart', 'ServerCallFun::managerStart');//管理进程开启后//设置工作/任务进程启动回调self::$serv->on('workerstart', 'ServerCallFun::onWorkstart');/*self::$serv->on('request',function ($request, $response) {$response->header("Content-Type", "text/html; charset=utf-8");$response->end("<h1>Hello Swoole. #".rand(1000, 9999)."</h1>");});*///监听连接进入事件self::$serv->on('connect',function ($serv, $fd) {echo "Client: Connect.\n";});//监听数据接收事件self::$serv->on('receive','ServerCallFun::onReceive');//监听连接关闭事件self::$serv->on('close',function ($serv, $fd) {echo "Client: Close.\n";});//在启动之前添加一个全局的内存tabel监控所有的进程状态//实例启动前执行(start前的状态全部是程序全局期)self::$serv->start();}Static Private function stop(){$pid = @file_get_contents(TMP_PATH . 'server.pid');if($pid){if(\swoole_process::kill($pid, 0))\swoole_process::kill($pid, 15);else{foreach(glob(TMP_PATH . '*.pid') as $filename){$pid = @file_get_contents($filename);if(\swoole_process::kill($pid, 0))\swoole_process::kill($pid, 9);@unlink($filename);}}die('Stop of Framework Success!' . PHP_EOL);}die('Framework not started!' . PHP_EOL);}}
Root::run();

进一步来了解下这里是主要用来干嘛的

首先是声明了当前的执行文件的绝对路径,这里pid_file一定是要绝对路径

这里运行start命令会调用start的方法,这里主要是设置配置参数然后开启swoole默认的tcp服务。swoole的回调函数我放到另外一个类中处理了,这里是为了理解swoole的生命周期有意为之。

设置的默认参数中比较重要的是pid_file这个参数,这个可以用来重启和关闭服务进程。

在start方法执行前,所有的require和变量都是在第一层swoole生命周期中为程序全局期。

回调函数类是

<?php
require_once 'CmdController.php';
class ServerCallFun{static function start(\swoole_server $server){\swoole_set_process_name("Master process");//绑定状态事件//\swoole_process::signal(SIGUSR1, '\Root\Http::status');//绑定重载事件\swoole_process::signal(SIGUSR2, function() use ($server){$server->reload();});}static function managerStart(\swoole_server $server){$num = count(glob(TMP_PATH . 'manager_*.pid'));file_put_contents(TMP_PATH . 'manager_'. $num .'.pid', $server->manager_pid);\swoole_set_process_name("Manager[{$num}] process");}static Public function onWorkstart(\swoole_server $server, int $worker_id){//实例化进程对象Root::$worker = new self();if($server->taskworker) {file_put_contents(TMP_PATH . "task_{$worker_id}.pid", $server->worker_pid);\swoole_set_process_name("Tasker[{$worker_id}] process ");echo "TaskID[{$worker_id}] PID[". $server->worker_pid ."] creation finish!" . PHP_EOL;} else {file_put_contents(TMP_PATH . "worker_{$worker_id}.pid", $server->worker_pid);\swoole_set_process_name("Worker[{$worker_id}] process");echo "WorkerID[{$worker_id}] PID[". $server->worker_pid ."] creation finish!" . PHP_EOL;}}static Public function onConnect($serv, $fd){}static Public function onReceive($serv, $fd, $from_id, $data){$msg = CmdController::run($data,$fd,$from_id);$serv->send($fd,json_encode($msg));}static Public function onClose($serv, $fd){}
}

这里我们在主进程开启后执行了start的回调,添加上了重启热更新子进程的信号siguser2.进行server reload.并且将进程名字设置为Master Process

对管理进程也设置了回调。也是为了更名

对work进程设置回调更名,同时因为是守护方式运行服务,php的输出会输出到log_file配置的路径中

然后我在测试receive中测试下进程全局期中会出现什么情况

<?php
class CmdController{static public $count = 0;static public function run($recive,$fd,$fromId){self::$count++;$returnArr = ['ret'=>-1,'data'=>'','msg'=>''];if($recive){$returnArr['ret']  = 0;$returnArr['data'] = self::$count.";{$fd}-{$fromId}:getRequest[{$recive}]->getReponse[Success]";}return $returnArr;}
}

如果是我们的理解,我们会认为每次tcp客户端发送数据,然后服务端接收到的话,就是让count+1。其实这里就是进程的全局期,4个work会独立保存各自的数据。所以会出现下面,count出现4次重复然后自增的情况。

如何开启测试的服务器 php index.php start

如何关闭测试的服务器 php index.php stop

转载于:https://www.cnblogs.com/gavinjunftd/p/9145379.html

利用Swoole编写一个TCP服务器,顺带测试下Swoole的4层生命周期相关推荐

  1. Python | Socket02 - 使用with语句建立一个TCP服务器(阻塞+单线程),将TCP客户端发过来的字符串原路返回

    一.前言 Python | Socket01 - 创建一个TCP服务器(阻塞+单线程),将TCP客户端发过来的字符串原路返回 在上一篇博文完成TCP服务器简单的收发程序后,发现在Python上有更加简 ...

  2. Python | Socket01 - 创建一个TCP服务器(阻塞+单线程),将TCP客户端发过来的字符串原路返回

    一.前言 使用Python可以很简单地创建一个TCP服务器程序,该TCP服务器的程序目的是完成这个功能:TCP客户端发送一段字符串给TCP服务端,TCP服务端将字符串原路返回去. 我是从该B站视频教程 ...

  3. 利用C#编写一个高斯正反算程序

    一.代码界面展示 整个界面控件为tabControl,groupBox,label,textbox,comboBox,button,richTextBook. 二.代码运算结果展示 数据结果采用国家统 ...

  4. python数据预测_利用Python编写一个数据预测工具

    利用Python编写一个数据预测工具 发布时间:2020-11-07 17:12:20 来源:亿速云 阅读:96 这篇文章运用简单易懂的例子给大家介绍利用Python编写一个数据预测工具,内容非常详细 ...

  5. 利用android实现汇率计算器,利用python编写一个汇率计算器

    利用python编写一个汇率计算器 发布时间:2020-11-10 15:03:44 来源:亿速云 阅读:137 作者:Leah 这篇文章运用简单易懂的例子给大家介绍利用python编写一个汇率计算器 ...

  6. 利用C#编写一个水准测量近似平差程序

    一.代码界面展示 整个界面主要就是就整个界面而言,其实主要使用到的控件就是Menu,tabControl,dataGridView,richtextbox. 二.代码运算结果展示 1.导入数据 这里就 ...

  7. 利用Python编写一个高斯正反算程序

    一.前言 这次的高斯正反算程序是使用的Python编写的. 环境信息是:Win10.PyCharm 2021.3.1.PySide6 6.3.1.Python 3.9.9,基于QT Designer设 ...

  8. Java基础——利用DMO4J编写一个商品管理系统

    题目:这里有一份XML文件用于储存商品信息,编写一个商品管理系统,可以对XML文件进行增删查改的操作. <?xml version="1.0" encoding=" ...

  9. python编写一个软件-软件代做:利用Python编写一个行业专用的小计算器

    前言:本文讲述的是如何利用python编程制作一个适用于指定行业的计算器,方便计算结果,涵盖的知识点由Python编写GUI界面程序,利用爬虫采集实时的汇率数据,将Python文件打包成可以单独运行的 ...

  10. 实战 | 如何利用 Scrapy 编写一个完整的爬虫!

    大家好,我是安果! 提到爬虫框架,这里不得不提 Scrapy,它是一款非常强大的分布式异步爬虫框架,更加适用于企业级的爬虫! 项目地址: https://github.com/scrapy/scrap ...

最新文章

  1. ZJU PAT 1027 Colors in Mars
  2. 无法找到脚本库错误解决过程
  3. git push的时候报411问题
  4. html 垂直线代码,html – Bootstrap 3水平和垂直分隔线
  5. 性能测试小总结(四) 结果分析(未完成)
  6. arduino esp8266_你还用Arduino?上PlatformIO开发Esp、AVR、STM32,十分钟亲测ESP8266
  7. cad文字提取到excel_别怕!CAD表格与EXCEL之间的转化,有它就够了
  8. php mb strlen 开启,php mb_strlen是什么函数
  9. ubuntu16.04安装pycharm,并设置快捷启动方式
  10. Oracle ORA-06861: 文字与格式字符串不匹配 记录两次无助的遭遇:存储过程直接执行正常,java调用存储过程则报错
  11. IDEA用maven创建springMVC项目和配置(XML配置和Java配置)
  12. Charles proxy tools 移动开发调试
  13. 十年回眸 中国游戏崛起的完美轨迹
  14. 日记 - idea中的中文注释出现乱码的解决方案
  15. Xcode 9以下(xip) 官方直接下载地址(离线下载)
  16. 豆丁网文档免登陆免积分下载工具原理分析
  17. cordova打包APP更改图标和APP名字
  18. 计算机网络是指将多台具有独立功能,计算机等级考试四级网络工程师2015年模拟试题及答案(三)...
  19. 十行python代码定时给微信好友发送晚安,自动应答--python云舔狗
  20. Helm — Chart介绍

热门文章

  1. 精选|2018年12月R新包推荐
  2. R语言ETL工程系列:总论
  3. 内推| 阿里全球化分析师战队集结令
  4. 手把手教你使用R语言做评分卡模型
  5. java中的多态与继承_Java中继承与多态
  6. VI 编辑器保存命令
  7. ios中input输入无效
  8. HDU 6122 今夕何夕 【数学公式】 (2017百度之星程序设计大赛 - 初赛(A))
  9. POJ 3020 Antenna Placement(无向二分图的最小路径覆盖)
  10. 让LinqToSQL使用Web.Config中的链接字符串(修改Settings.Designer.cs)