利用Swoole编写一个TCP服务器,顺带测试下Swoole的4层生命周期
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
利用Swoole编写一个TCP服务器,顺带测试下Swoole的4层生命周期的更多相关文章
- 如何编写一个 SendFile 服务器
如何编写一个 SendFile 服务器 前言 之前讨论零拷贝的时候,我们知道,两台机器之间传输文件,最快的方式就是 send file,众所周知,在 Java 中,该技术对应的则是 FileChann ...
- Swoole学习(七)Swoole之异步TCP服务器的创建
环境:Centos6.4,PHP环境:PHP7 <?php //创建TCP服务器 /** * $host 是swoole需要监听的ip,如果要监听本地,不对外服务,那么就是127.0.0.1;如 ...
- 使用.net core在Ubuntu构建一个TCP服务器
介绍和背景 TCP编程是网络编程领域最有趣的部分之一.在Ubuntu环境中,我喜欢使用.NET Core进行TCP编程,并使用本机Ubuntu脚本与TCP服务器进行通信.以前,我在.NET框架本身写了 ...
- 利用javafx编写一个时钟制作程序
1.首先创建一个时钟类,用于编写时钟的各种特有属性 package javaclock; /** * * @author admin */import java.util.Calendar;impor ...
- 27、通过visual s'tudio 验证 SOCKET编程:搭建一个TCP服务器
本文就是在windows下进行socket编程,搭建一个TCP客户端. 在visual studio下编程,首先在windows下进行初始化(这点在linux下是不需要的): /* 初始化 Winso ...
- 测试微信小程序页面的生命周期
前言:本人是一个初学者,也是第一次写博客,敲键盘的时候还不知道发布后是什么效果,希望内容给其他初学的同学一点帮助,同时加深自己的理解.这篇随笔讲的是Page页面的生命周期,在开发中是基础中的基础,很容 ...
- 如何利用tomcat搭建一个动态服务器
这篇文章只记录已解压缩包的方式安装,通常linux服务器上也是这样. 1.下载tomcat.zip压缩包. http://tomcat.apache.org/download-70.cgi 2.把zi ...
- 01.swoole学习笔记--TCP服务器
1.安装swoole扩展 2.网络调试助手进行调试 <?php //创建服务器 $host='192.168.10.31'; $port=; //$model='SWOOLE_PROCESS'; ...
- 13.首先,编写一个类ChongZai,该类中有3个重载的方法void print();其次, 再编写一个主类来测试ChongZai类的功能。
package java1; //计算器 public class Jisuanqi { //属性 //型号,品牌等 //重载 //1.方法同名不同参 //2.返回类型和重载无关 //3.多态的一种表 ...
随机推荐
- struts2与spring整合时需要注意的点
首先我们需要明白spring整合struts2中的什么东西,spring中的核心就是IOC和AOP,IOC是对象的容器,AOP是处理动态代理的;比如spring与hibernate整合时就要用到aop ...
- JAVA&PYTHON
- 查询结果null替换为0
xxx表示字段名 mysql数据库 : ifnull( xxx , 0 ) oracle数据库: NVL(xxx , 0 )
- Python 函数内变量的作用域
Python程序中创建.改变.查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域. 全局作用域(global):即在模块层次中定义的变量,每一个模块都是一个全局作用域 ...
- python模块部分 re模块 之正则表达式
python 全栈开发 1.什么是模块 2.正则表达式 一.什么是模块? 1.模块: 是一组功能的集合 你要和一个东西打交道,但是这个东西本身和python没有关系,这个东西本身就存在, 这时,pyt ...
- python3 获得shell的输出内容(subprocess.getstatusoutput)
默认通过os.system(“shell")命令赋值,结果是0之类的,0表示shell命令运行正确 如果想获得shell输出的内容,可以通过[subprocess.getstatusoutp ...
- vue / js使用video获取视频时长
项目中遇到上传视频功能,需要有预览和获取视频时长功能,因之前使用upload(有需要的话可以参考下我之前的文章),这里就不赘述,直接用来上传视频,不过在上传之前和上传成功后的钩子里,获取不到时长: 没 ...
- navicat连接虚拟机中mysql"Access denied for user'root'@'IP地址'"问题
登陆要链接的服务器上的mysql 命令:mysql -uroot -p123456 然后执行 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED ...
- Centos7在虚拟机中扩展磁盘空间
说明 情况:已经在VirtualBox虚拟机创建了一个磁盘并已经装好了系统,发现磁盘空间太小,需要再添加一个磁盘的大小.或者说Centos7系统需要扩展磁盘空间. 步骤 1.VirtualBox新建磁 ...
- 微信小程序开发——导航失效的解决办法
异常描述: 使用 navigator 导航,各种属性配置没问题,就是点击死活不跳转. 异常分析: 遇到这种情况,要先考虑的就是当前配置的导航url,是不是已经使用在tabBar中,因为小程序对于nav ...