Linux下搭建swoole实现php消息推送的方法
发布:smiling 来源: PHP粉丝网 添加日期:2024-04-28 15:13:40 浏览: 评论:0
Swoole使用纯C语言编写,提供了PHP语言的异步多线程服务器,异步 TCP/UDP 网络客户端,异步 MySQL,异步 Redis,数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件读写,异步DNS查询。 Swoole内置了Http/WebSocket服务器端/客户端、Http2.0服务器端,完美支持PHP语言。本文讲解Linux下搭建swoole实现php消息推送的方法。
swoole简介
Swoole是一个面向生产环境的 PHP 异步网络通信引擎,使 PHP 开发人员可以编写高性能的异步并发 TCP、UDP、Unix Socket、HTTP,WebSocket 服务。Swoole 可以广泛应用于互联网、移动通信、企业软件、云计算、网络游戏、物联网(IOT)、车联网、智能家居等领域。 使用 PHP + Swoole 作为网络通信框架,可以使企业 IT 研发团队的效率大大提升。
Swoole不是一个像Zend Framework、CakePHP、Yii、symfony、ThinkPHP等一样的框架,也不是一个像WordPress、Drupal、Discuz、UChome等开源产品看齐的项目。 Swoole的目标是向Java框架、Ruby On Rails、Python DjangoPylons等一流框架发起挑战。
Swoole虽然是标准的PHP扩展,实际上与普通的扩展不同。普通的扩展只是提供一个库函数。而Swoole扩展在运行后会接管PHP的控制权,进入事件循环。当IO事件发生后底层会自动回调指定的PHP函数。
包含以下几个特色功能:
1、 类似ORM的数据查询,提供SQL封装器,让MySQL的SQL与PHP的Array,会话,Cache无缝结合。
2、App MVC分层结构,有效的程序结构分层,提高程序的可维护性和扩展性,实现低耦合,基于接口开发。
3、集成大量,实用的功能,比如方便的数据库操作,模板操作,缓存操作,系统配置,表单处理,分页,数据调用,字典操作,上传处理,内容编辑,调试等。
4、模板-数据反射系统,可以直接在模板中调用数据,提供很多标签,可以无需修改程序,只修改模板,即可实现网站各类更新维护工作。
另外的几个功能
1、Swoole包含了大量类,提供众多的功能扩展,基本上Web开发能够用到的功能类,大部分都可以在Swoole框架中找到。
2、Swoole拥有插件系统,Fckeditor、Adodb、pscws中文分词、中文全文索引系统、最新的Key-Value数据库思想,TokyoTyrant,可以无限扩展框架的功能。
安装swoole服务
1.下载swoole源码,下载地址: https://github.com/swoole/swoole-src/releases
2.将tar包上传到/usr/local/src/swoole下面,这里面存储安装源文件。
3.解压源文件,tar –xvfswoole.tar
4.进入到刚解压的目录下输入命令phpize
5.注意:phpize是php-devel中的东西,它可以给PHP动态添加扩展,所以,请确保你的机器上安装了php-devel软件包。
6.接着,依次输入如下命令:./configure,执行编译检测make,编译swoole
7.缺少pcre和pcre-devel相关软件包,安装上即可。
8.sudo make install
9.php.ini一般在etc下面 编译安装成功后,我们还需要修改php.ini,在其中加入swoole.so扩展:
10.extension=swoole.so
11.输入php -m中能查看到swoole说明扩展安装成功。
安装apache启动swoole服务
(1)测试是否安装正确启动swoole Php服务
(2)在apache中添加server.php文件,和client.php文件。一般目录在var/www/html下面
(3)打开两个终端 在这两个文件所在的目录下面打开这两个文件,可以实现socket长连接服务。
安装lsof:yum -y install lsof
Server端PHP程序
- class WebSocketService {
- private static $instance = NULL;
- public $tagindex = 0;
- public $server = null;
- public $office_cache = null;
- public $timer_arr = []; //该变量保存所有的定时器任务ID,每一个客户端可以通过$timer_arr[客户端ID]
- 得到该客户端建立的所有定时器
- public $conf = [
- 'host' => '0.0.0.0',
- 'port' => 9999, //服务使用端口
- 'worker_num' => 2, //启动worker进程数
- 'task_worker_num' => 8, //启动task进程数
- 'is_daemonize' => 0, //是否后台运行:0-否,1-是
- 'log_file' =>'/tmp/swoole_webSocket_server.log', //日志文件路径
- 'abc' =>0,
- ];
- public function getTagIndex() {
- return $this->conf['abc'];
- }
- public function setSetTagIndex($index) {
- $this->conf['abc'] = 100;
- echo $this->getTagIndex();
- }
- public function __construct($config = []) {
- $this->office_cache = array('1' => '1', '3'=>'2');
- $this->conf = array_merge($this->conf, (array)$config);
- }
- //静态方法,返回此类唯一实例
- public static function getInstance(){
- if(emptyempty(self::$instance)){
- echo "instance \n";
- self::$instance=new WebSocketService();
- }
- return self::$instance;
- }
- /**
- * 服务器端运行webSocket的入口
- */
- public function run() {
- try {
- $this->server = new \swoole_websocket_server($this->conf['host'],$this->conf['port']);
- $this->server->set(
- [
- 'worker_num' => $this->conf['worker_num'],
- 'task_worker_num' =>$this->conf['task_worker_num'],
- 'daemonize' => $this->conf['is_daemonize'],
- 'log_file' => $this->conf['log_file'],
- ]
- );
- //注册方法列表
- $this->server->on('open', [$this, 'open']);
- $this->server->on('message', [$this, 'message']);
- $this->server->on('task', [$this, 'task']);
- $this->server->on('finish', [$this, 'finish']);
- $this->server->on('close', [$this, 'close']);
- $this->server->start();
- } catch (\Exception $e) {
- var_dump($e->getCode() . ':' . $e->getMessage());
- }
- }
- /**
- * 建立socket链接时,执行方法
- * @param $server
- * @param $request
- */
- public function open($server, $request) {
- $data = [
- 'client_id' => $request->fd,
- 'request' => $request
- ];
- echo 'open<<'.$data['client_id'];
- $this->doOpen($data);
- }
- /**
- * 发送消息时,执行方法
- * @param $server
- * @param $frame
- */
- public function message($server, $frame) {
- echo "GET_mesage\n";
- $data = [
- 'client_id' => $frame->fd,
- 'data' => $frame->data,
- 'frame' => $frame,
- ];
- $this->doMessage($data);
- }
- /**
- * 执行具体任务
- * @param $server
- * @param $task_id
- * @param $from_id
- * @param $data
- */
- public function task($server, $task_id, $from_id, $data) {
- $data['task_id'] = $task_id;
- $data['from_id'] = $from_id;
- $this->doTask($data);
- }
- /**
- * 任务结果处理
- * @param $server 服务器对象
- * @param $taskId 任务进程ID
- * @param $data
- */
- public function finish($server, $taskId, $data) {
- $data['task_id'] = $taskId;
- $this->doFinish($data);
- }
- /**
- * 关闭链接
- * @param $server 服务器对象
- * @param $client_id 客户端唯一标识
- */
- public function close($server, $client_id) {
- $data = [
- 'client_id' => $client_id
- ];
- $this->doClose($data);
- }
- /**
- * 客户端成功连接到服务器时,会触发该方法
- * 子类根据需求重写该方法
- * @param $data
- * [
- * 'client_id', //客户端唯一标识
- * 'data', //一些请求数据
- * 'frame', //swoole的数据
- * ];
- */
- public function doOpen($data) {
- echo "建立连接成功";
- }
- /**
- * 得到Swoole Websocket Server
- *
- * @return null|\swoole_websocket_server
- */
- public function getServer()
- {
- return $this->server;
- }
- /**
- * 收到客户端发来的消息,会触发该方法
- * 子类根据需求重写该方法
- * @param $data
- * [
- * 'client_id', //客户端唯一标识
- * 'data', //客户端发送过来的消息(数据)
- * 'frame', //swoole的数据
- * ];
- */
- public function doMessage($data) {
- $info = json_decode($data['data'],true);
- $officeid = $info['officeid'];
- $client_id = $data['client_id'];
- echo"<<<<".$officeid.">>>>".$client_id."\r\n";
- if ($officeid == 1) {
- $this->sendMsgToClient('2',array('msg' =>'我是1号场地发送给你数据'));
- } else {
- $this->sendMsgToClient('1',array('msg' =>'我是3号场地发送给你数据'));
- }
- }
- /**
- * 具体的工作任务。需要通过 $this->doJob()来触发
- * 子类根据需求重写该方法
- * @param $data
- * [
- * 'client_id', //客户端唯一标识
- * ];
- */
- public function doTask($data) {
- }
- /**
- * 工作的结果处理。
- * 子类根据需求重写该方法
- * @param $data
- * [
- * 'client_id', //客户端唯一标识
- * ];
- */
- public function doFinish($data) {
- }
- /**
- * 客户端断开时会自动触发该方法
- * 子类根据需求重写该方法
- * @param $data
- * [
- * 'client_id', //客户端唯一标识
- * ];
- */
- public function doClose($data) {
- }
- /**
- * 发送任务
- * @param $data 必须是数组,且要有$data['client_id']
- */
- public function doJob($data) {
- $this->server->task($data);
- }
- public function finishJob($data) {
- $this->server->finish($data);
- }
- /**
- * 发送消息到客户端
- * @param $client_id
- * @param $msg
- */
- public function sendMsgToClient($client_id, $msg) {
- echo "发送信息给客户端:{$client_id} | {$msg['action']['name']} | " . date('Y-m-dH:i:s') . "\r\n";
- $this->server->push($client_id, json_encode($msg));
- }
- /**
- * 关闭客户端链接
- * @param $client_id
- */
- public function closeClient($client_id) {
- $this->server->close($client_id);
- }
- /**
- * 添加定时器
- * @param $client_id
- * @param $tick_time
- */
- public function addTimer($client_id, $tick_time) {
- //暂未实现,先使用swoole原生写法
- }
- /**
- * 清除定时器
- * @param $client_id
- * @param $arr
- */
- public function clearTimer($client_id, &$arr) {
- if (is_array($arr)) {
- foreach ($arr[$client_id] as $val) {
- if (is_array($val)) {
- foreach ($val as $v) {
- swoole_timer_clear($v);
- }
- } else {
- swoole_timer_clear($val);
- }
- }
- }
- unset($arr[$client_id]);
- }
- }
html前端javascript程序
- $(document).ready(function(){
- varwsurl = "ws://182.92.101.206:9999/";
- console.log(wsurl);
- varwebsocket = new WebSocket(wsurl);
- websocket.onopen= function(evt){
- console.log('Server: 打开WebSocket连接');
- };
- websocket.onclose= function(evt){
- console.log('Server: 关闭WebSocket连接');
- };
- websocket.onmessage= function(evt){
- varres = JSON.parse(evt.data);
- console.log('Server: 收到消息(来自:'+res+'请求)');
- console.log(res);
- };
- websocket.οnerrοr= function(evt){
- console.log('Server: 出现错误');
- console.log(evt.data);
- }
- functiondoSend(msg){
- console.log('Client:发送消息 ' + msg);
- websocket.send(msg);
- }
- });
启动start.php文件
启动start.php文件,cd到指定目录下,然后PHP-CLI运行php start.php,这种方式是没有启用线程保护的关掉后程序结束线程还在占用。
- require'src/WebSocketSwoole/WebSocketService.php';
- // require './WebSocketService.php';
- session_start();
- // $demoService = new\WebSocketSwoole\WebSocketService();
- $demoService =\WebSocketSwoole\WebSocketService::getInstance();
- $demoService->run();
Tags: Linux搭建swoole php消息推送
- 上一篇:Linux下查看PHP配置文件php.ini的位置
- 下一篇:最后一页
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)