Windows版安装
-
安装thinkphp5;
composer create-project topthink/think tp5 --prefer-dist
-
进入tp5的目录,安装Windows版本的workerman;
composer require workerman/workerman-for-win
-
安装Windows版本的gateway;
composer require workerman/gateway-worker-for-win
服务端实现
控制器:app\push\controller\Sregister
<?php
namespace app\push\controller;
use \Workerman\Worker;
use \GatewayWorker\Register;
class Sregister
{
public function __construct()
{
// register 必须是text协议
$register = new Register('text://0.0.0.0:1236');
// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}
}
}
控制器:app\puah\controller\Sgateway
<?php
namespace app\push\controller;
use \Workerman\Worker;
use \Workerman\WebServer;
use \GatewayWorker\Gateway;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;
class Sgateway
{
public function __construct()
{
// gateway 进程,这里使用Text协议,可以用telnet测试
$gateway = new Gateway("Text://0.0.0.0:8013");
// gateway名称,status方便查看
$gateway->name = 'shareac';
// gateway进程数
$gateway->count = 4;
// 本机ip,分布式部署时使用内网ip
$gateway->lanIp = '127.0.0.1';
// 内部通讯起始端口,假如$gateway->count=4,起始端口为4000
// 则一般会使用4000 4001 4002 4003 4个端口作为内部通讯端口
$gateway->startPort = 2900;
// 服务注册地址
$gateway->registerAddress = '127.0.0.1:1236';
// 心跳间隔
$gateway->pingInterval = 55;
$gateway->pingNotResponseLimit = 3;
// 心跳数据
// $gateway->pingData = '{"type":"ping"}';
/*
// 当客户端连接上来时,设置连接的onWebSocketConnect,即在websocket握手时的回调
$gateway->onConnect = function($connection)
{
$connection->onWebSocketConnect = function($connection , $http_header)
{
// 可以在这里判断连接来源是否合法,不合法就关掉连接
// $_SERVER['HTTP_ORIGIN']标识来自哪个站点的页面发起的websocket链接
if($_SERVER['HTTP_ORIGIN'] != 'http://kedou.workerman.net')
{
$connection->close();
}
// onWebSocketConnect 里面$_GET $_SERVER是可用的
// var_dump($_GET, $_SERVER);
};
};
*/
// 如果不是在根目录启动,则运行runAll方法
if (!defined('GLOBAL_START')) {
Worker::runAll();
}
}
}
控制器:app\push\controller\Sbusinessworker
<?php
namespace app\push\controller;
use \Workerman\Worker;
use \Workerman\WebServer;
use \GatewayWorker\Gateway;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;
class Sbusinessworker
{
public function __construct()
{
// bussinessWorker 进程
$worker = new BusinessWorker();
// worker名称
$worker->name = 'shareacWorker';
// bussinessWorker进程数量
$worker->count = 4;
// 服务注册地址
$worker->registerAddress = '127.0.0.1:1236';
$worker->eventHandler = 'app\push\controller\Events';
// 如果不是在根目录启动,则运行runAll方法
if (!defined('GLOBAL_START')) {
Worker::runAll();
}
}
}
控制器:app\push\controller\Sgatewaywebsocket
<?php
namespace app\push\controller;
use \Workerman\Worker;
use \Workerman\WebServer;
use \GatewayWorker\Gateway;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;
class Sgatewaywebsocket
{
public function __construct()
{
// 证书最好是申请的证书
//$context = array(
// // 更多ssl选项请参考手册 http://php.net/manual/zh/context.ssl.php
// 'ssl' => array(
// // 请使用绝对路径
// 'local_cert' => '/home/jhq/ssl/smartlife.pem', // 也可以是crt文件
// 'local_pk' => '/home/jhq/ssl/smartlife.key',
// 'verify_peer' => false,
// // 'allow_self_signed' => true, //如果是自签名证书需要开启此选项
// )
//);
// gateway 进程,这里使用Text协议,可以用telnet测试
$gateway = new Gateway("Websocket://0.0.0.0:2346");
// 开启SSL,websocket+SSL 即wss
//$gateway->transport = 'ssl';
// gateway名称,status方便查看
$gateway->name = 'shareacApp';
// gateway进程数
$gateway->count = 4;
// 本机ip,分布式部署时使用内网ip
$gateway->lanIp = '127.0.0.1';
// 内部通讯起始端口,假如$gateway->count=4,起始端口为4000
// 则一般会使用4000 4001 4002 4003 4个端口作为内部通讯端口
$gateway->startPort = 3000;
// 服务注册地址
$gateway->registerAddress = '127.0.0.1:1236';
// 心跳间隔
// $gateway->pingInterval = 55;
// $gateway->pingNotResponseLimit = 1;
// 心跳数据
// $gateway->pingData = '{"type":"ping"}';
/*
// 当客户端连接上来时,设置连接的onWebSocketConnect,即在websocket握手时的回调
$gateway->onConnect = function($connection)
{
$connection->onWebSocketConnect = function($connection , $http_header)
{
// 可以在这里判断连接来源是否合法,不合法就关掉连接
// $_SERVER['HTTP_ORIGIN']标识来自哪个站点的页面发起的websocket链接
if($_SERVER['HTTP_ORIGIN'] != 'http://kedou.workerman.net')
{
$connection->close();
}
// onWebSocketConnect 里面$_GET $_SERVER是可用的
// var_dump($_GET, $_SERVER);
};
};
*/
// 如果不是在根目录启动,则运行runAll方法
if (!defined('GLOBAL_START')) {
Worker::runAll();
}
}
}
控制器:app\push\controller\Events
<?php
namespace app\push\controller;
use app\common\controller\Worker;
use GatewayWorker\Lib\Gateway;
class Events
{
/**
* 当客户端连接时触发
* 如果业务不需此回调可以删除onConnect
*
* @param int $client_id 连接id
*/
public static function onConnect($client_id)
{
}
/**
* 当客户端发来消息时触发
* @param int $client_id 连接id
* @param mixed $message 具体消息
*/
public static function onMessage($client_id, $message)
{
$message = json_decode($message, 1);
/*业务逻辑控制器*/
$con = new Worker();
switch ($message['Type']) {
case 'reg':
//接收登录包
$verify = $con->verify($message['Key'], $message['Imei']);
if (!$verify) {
return Gateway::closeClient($client_id); //验证失败,断开连接
}
$_SESSION['uid'] = $message['Imei'];
Gateway::bindUid($client_id, $message['Imei']);
$data['Type'] = 'reg';
$data['Time'] = time();
$sendData = '0' . json_encode($data);
Gateway::sendToClient($client_id, $sendData);
$con->saveHeart($_SESSION['uid'], $message, 'reg'); //存心跳状态
break;
case 'heartbeat':
//接收心跳包
if (!isset($_SESSION['uid'])) {
return Gateway::closeClient($client_id); //设备未登录,断开连接
}
$data['Type'] = 'reply';
$data['Time'] = time();
$sendData = '0' . json_encode($data);
Gateway::sendToClient($client_id, $sendData);
$con->saveHeart($_SESSION['uid'], $message, 'heartbeat'); //更新心跳包数据
break;
/*其他接收类型按需求补充……*/
}
}
/**
* 当用户断开连接时触发
* @param int $client_id 连接id
*/
public static function onClose($client_id)
{
$con = new Worker();
//设备心跳断开
if ($_SESSION['uid'] && !Gateway::isUidOnline($_SESSION['uid'])) {
$con->offline($_SESSION['uid']);
}
}
}
在项目根目录 新增入口文件 start_register.php 、start_gateway.php 、start_businessworker.php、start_gateway_websocket.php四个入口文件
文件:start_register.php
<?php
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','push/Sregister');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
文件:start_gateway.php
<?php
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','push/Sgateway');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
文件:start_businessworker.php
<?php
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','push/Sbusinessworker');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
文件:start_gateway_websocket.php
<?php
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','push/Sgatewaywebsocket');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
- 由于PHP-CLI在windows系统无法实现多进程以及守护进程,所以只能把三个文件放到bat文件,然后双击启动
bat文件:start_for_win.bat
php start_register.php start_gateway.php start_businessworker.php start_gateway_websocket.php pause
linux版安装
- 安装thinkphp5;
composer create-project topthink/think tp5 --prefer-dist
- 进入tp5的目录,安装linux版本的workerman;
composer require topthink/think-worker
- 安装linux版本的gateway;
composer require workerman/gateway-worker
- 关键部分,服务端实现
复制代码
控制器 app\push\controller\Gate
<?php
namespace app\push\controller;
use Workerman\Worker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use GatewayWorker\BusinessWorker;
class Gate
{
/**
* 构造函数
* @access public
*/
public function __construct()
{
//初始化各个GatewayWorker
//初始化register register 服务必须是text协议
$register = new Register('text://0.0.0.0:1236');
//初始化 bussinessWorker 进程
$worker = new BusinessWorker();
// worker名称
$worker->name = 'shareacWorker';
// bussinessWorker进程数量
$worker->count = 4;
// 服务注册地址
$worker->registerAddress = '127.0.0.1:1236';
//设置处理业务的类,此处制定Events的命名空间
$worker->eventHandler = 'app\push\controller\Events';
/*面向硬件*/
// 初始化 gateway 进程
$gateway = new Gateway("Text://0.0.0.0:8013");
// 设置名称,方便status时查看
$gateway->name = 'shareac';
$gateway->count = 4;
// 分布式部署时请设置成内网ip(非127.0.0.1)
$gateway->lanIp = '127.0.0.1';
// 内部通讯起始端口,假如$gateway->count=4,起始端口为4000
// 则一般会使用4000 4001 4002 4003 4个端口作为内部通讯端口
$gateway->startPort = 2900;
// 心跳间隔
$gateway->pingInterval = 55;
$gateway->pingNotResponseLimit = 3;
// 心跳数据
// $gateway->pingData = '{"type":"ping"}';
// 服务注册地址
$gateway->registerAddress = '127.0.0.1:1236';
/*面向小程序*/
// 证书最好是申请的证书
$context = array(
'ssl' => array(
// 请使用绝对路径
'local_cert' => '磁盘路径/server.pem', // 也可以是crt文件
'local_pk' => '磁盘路径/server.key',
'verify_peer' => false,
// 'allow_self_signed' => true, //如果是自签名证书需要开启此选项
)
);
$gateway_web = new Gateway("Websocket://0.0.0.0:2346", $context);
// 开启SSL,websocket+SSL 即wss
$gateway_web->transport = 'ssl';
// gateway名称,status方便查看
$gateway_web->name = 'shareacApp';
// gateway进程数
$gateway_web->count = 4;
// 本机ip,分布式部署时使用内网ip
$gateway_web->lanIp = '127.0.0.1';
// 内部通讯起始端口,假如$gateway->count=4,起始端口为4000
// 则一般会使用4000 4001 4002 4003 4个端口作为内部通讯端口
$gateway_web->startPort = 3000;
// 服务注册地址
$gateway_web->registerAddress = '127.0.0.1:1236';
//运行所有Worker;
Worker::runAll();
}
}
入口文件
文件:start.php
<?php
/**
* workerman + GatewayWorker
* 此文件只能在Linux运行
* run with command
* php start.php start
*/
ini_set('display_errors', 'on');
if(strpos(strtolower(PHP_OS), 'win') === 0)
{
exit("start.php not support windows.\n");
}
//检查扩展
if(!extension_loaded('pcntl'))
{
exit("Please install pcntl extension. See http://doc3.workerman.net/appendices/install-extension.html\n");
}
if(!extension_loaded('posix'))
{
exit("Please install posix extension. See http://doc3.workerman.net/appendices/install-extension.html\n");
}
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','push/Gate');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
启动程序
php start.php start
本文借鉴来源:https://blog.csdn.net/niefudong/article/details/96473456