Swoole 结合TP5搭建文字直播平台
直播模块流程:

主进程服务:主进程同时开启两个服务
- http服务,负责向前端传递页面,处理登录等事务
- websocket服务,服务处理直播以及聊天室等事务
在项目根目录(框架代码同级目录)建立script目录,用于存放脚本文件
ws.php : 主进程服务
<?php
/**
* Created by PhpStorm.
* User: baidu
* Date: 18/3/27
* Time: 上午12:50
*/
class Ws {
CONST HOST = "0.0.0.0";
CONST PORT = 8811;
CONST CHART_PORT = 8812; public $ws = null;
public function __construct() {
// 启动服务时清空redis
//开启HTTP服务
$this->ws = new swoole_websocket_server(self::HOST, self::PORT);
//添加端口,用于websocket服务
$this->ws->listen(self::HOST, self::CHART_PORT, SWOOLE_SOCK_TCP);
$this->ws->set(
[
'enable_static_handler' => true,
'document_root' => "/home/work/hdtocs/swoole_mooc/thinkphp/public/static",
'worker_num' => 4,
'task_worker_num' => 4,
]
);
$this->ws->on("start", [$this, 'onStart']);
$this->ws->on("open", [$this, 'onOpen']);
$this->ws->on("message", [$this, 'onMessage']);
$this->ws->on("workerstart", [$this, 'onWorkerStart']);
$this->ws->on("request", [$this, 'onRequest']);
$this->ws->on("task", [$this, 'onTask']);
$this->ws->on("finish", [$this, 'onFinish']);
$this->ws->on("close", [$this, 'onClose']); $this->ws->start();
} /**
* @param $server
*/
public function onStart($server) {
swoole_set_process_name("live_master");
}
/**
* @param $server
* @param $worker_id
*/
public function onWorkerStart($server, $worker_id) {
// 定义应用目录
define('APP_PATH', __DIR__ . '/../../../application/');
// 加载框架里面的文件
require __DIR__ . '/../thinkphp/base.php';
} /**
* request回调
* @param $request
* @param $response
*/
public function onRequest($request, $response) {
if ($request->server['request_uri'] == '/favicon.ico') {
$response->status(404);
$response->end();
return;
}
$_SERVER = [];
if (isset($request->server)) {
foreach ($request->server as $k => $v) {
$_SERVER[strtoupper($k)] = $v;
}
}
if (isset($request->header)) {
foreach ($request->header as $k => $v) {
$_SERVER[strtoupper($k)] = $v;
}
} $_GET = [];
if (isset($request->get)) {
foreach ($request->get as $k => $v) {
$_GET[$k] = $v;
}
}
$_FILES = [];
if (isset($request->files)) {
foreach ($request->files as $k => $v) {
$_FILES[$k] = $v;
}
}
$_POST = [];
if (isset($request->post)) {
foreach ($request->post as $k => $v) {
$_POST[$k] = $v;
}
} $this->writeLog();
$_POST['http_server'] = $this->ws; ob_start();
// 执行应用并响应
try {
think\Container::get('app', [APP_PATH])
->run()
->send();
} catch (\Exception $e) {
// todo
} $res = ob_get_contents();
ob_end_clean();
$response->end($res);
} /**
* @param $serv
* @param $taskId
* @param $workerId
* @param $data
*/
public function onTask($serv, $taskId, $workerId, $data) {
//common/task/Task.php 所有任务都保存在这个类下
// 分发 task 任务机制,让不同的任务 调用该类下相应方法
$obj = new app\common\lib\task\Task;
$method = $data['method'];
$flag = $obj->$method($data['data'], $serv);
return $flag; // 告诉worker
} /**
* @param $serv
* @param $taskId
* @param $data
*/
public function onFinish($serv, $taskId, $data) {
echo "taskId:{$taskId}\n";
echo "finish-data-sucess:{$data}\n";
} /**
* 监听ws连接事件
* @param $ws
* @param $request
*/
public function onOpen($ws, $request) {
// fd redis [1]
\app\common\lib\redis\Predis::getInstance()->sAdd(config('redis.live_game_key'), $request->fd);
var_dump($request->fd);
} /**
* 监听ws消息事件
* @param $ws
* @param $frame
*/
public function onMessage($ws, $frame) {
echo "ser-push-message:{$frame->data}\n";
$ws->push($frame->fd, "server-push:" . date("Y-m-d H:i:s"));
} /**
* close
* @param $ws
* @param $fd
*/
public function onClose($ws, $fd) {
// fd del
\app\common\lib\redis\Predis::getInstance()->sRem(config('redis.live_game_key'), $fd);
echo "clientid:{$fd}\n";
} /**
* 记录日志
*/
public function writeLog() {
$datas = array_merge(['date' => date("Ymd H:i:s")], $_GET, $_POST, $_SERVER); $logs = "";
foreach ($datas as $key => $value) {
$logs .= $key . ":" . $value . " ";
} swoole_async_writefile(APP_PATH . '../runtime/log/' . date("Ym") . "/" . date("d") . "_access.log", $logs . PHP_EOL, function ($filename) {
// todo
}, FILE_APPEND); }
} new Ws();
直播推送代码: /application/admin/controller/Live.php
class Live
{
public function push() {
if(empty($_POST)) {
//返回错误信息
return Util::show(config('code.error'), 'error');
}
$data = [
// 这里获取直播管理页面传递过来的数据
];
// 获取连接的用户
// 赛况的基本信息入库 2、数据组织好 push到直播页面
$taskData = [
'method' => 'pushLive',
'data' => $data
];
//Task类中 pushLive 方法负责推送数据
$_POST['http_server']->task($taskData);
//返回成功给管理页面
return Util::show(config('code.success'), 'ok');
} }
Task类 /application/common/task/Task.php
class Task {
/**
* 通过task机制发送赛况实时数据给客户端
* @param $data
* @param $serv swoole server对象
*/
public function pushLive($data, $serv) {
$clients = Predis::getInstance()->sMembers(config("redis.live_game_key"));
foreach($clients as $fd) {
$serv->push($fd, json_encode($data));
}
}
}
Swoole 结合TP5搭建文字直播平台的更多相关文章
- 零基础如何一步一步开始搭建高性能直播平台?现以GitChat·架构来进行说明
前言 现在直播已经成为移动互联网时代一个新的重要流量入口,从YY.斗鱼到花椒直播,直播已经成为人们分享交流的新方式,应用场景众多,主要分为: 金融类直播:金融直播可应用于实时解盘,在线专家讲座,专家在 ...
- Java零基础搭建实时直播平台
https://www.cnblogs.com/scywkl/p/12101437.html
- fir.im Weekly - 从零开始,搭建理想的直播平台
2016年苹果发布会如期而至,新一代的 iPhone 7, Apple Watch 同时亮相,可惜大家期待的 MacBookPro.AR.VR产品并未出现.不论大家对新产品是"买买买&quo ...
- PHP直播平台源码搭建教程
直播源码市场火爆,但是PHP直播平台源码的搭建过程较为复杂,本文就简单为大家概述一下直播的实现过程以及PHP直播平台源码是如何搭建的. 一.直播的定义 如今PHP直播平台源码绝大部分情况下是指在现场架 ...
- 直播平台源码搭建教程:微信小程序中的直播如何去掉水印
直播平台源码搭建教程:微信小程序中的直播如何去掉水印 本文与大家分享一下直播平台源码搭建教程,如何去掉直播视频的水印 var services = require('../../lib/service ...
- 转:鏖战双十一-阿里直播平台面临的技术挑战(webSocket, 敏感词过滤等很不错)
转自:http://www.infoq.com/cn/articles/alibaba-broadcast-platform-technology-challenges 鏖战双十一-阿里直播平台面临的 ...
- 快速搭建一个直播Demo
缘由 最近帮朋友看一个直播网站的源码,发现这份直播源码借助 阿里云 .腾讯云这些大公司提供的SDK 可以非常方便的搭建一个直播网站.下面我们来给大家讲解下如何借助 腾讯云 我们搭建一个简易的 直播示例 ...
- [微信小程序直播平台开发]___(一)介绍与流程
1.一个可以忽略的前言 最近在做的一个项目,客户要做一个直播平台,主播发起视频直播,然后其他人进入房间观看这样子,跟其他直播平台不同的是,主播可以打赏观众,噗. 因为客户要做的是一个民宿的微信小程序, ...
- 用开源NGINX-RTMP-MODULE搭建FLASH直播环境
用开源nginx-rtmp-module搭建flash直播环境 1.将nginx和nginx-rtmp-module的源码包解压PS:nginx-rtmp-module网址https://github ...
随机推荐
- Jenkins的详细安装
操作环境:Windows 一.环境准备 1 安装JDK 本文采用jdk-8u111-windows-x64.exe: 2 配置tomcat 本文采用tomcat8,无需安装,配置JAVA_HOME及J ...
- [蓝桥杯]ALGO-95.算法训练_2的次幂表示
题目描述: 问题描述 任何一个正整数都可以用2进制表示,例如:137的2进制表示为10001001. 将这种2进制表示写成2的次幂的和的形式,令次幂高的排在前面,可得到如下表达式:=^+^+^ 现在约 ...
- WhereHows前后端配置文件
前端: # This is the main configuration file for the application. # ~~~~~ # Secret key # ~~~~~ # The se ...
- bzoj 4811: [Ynoi2017]由乃的OJ
树链剖分,用zkw线段树维护每条链两个方向上对每一位的变换情况,由于位数较少,可以用两个unsigned long long表示 #include<cstdio> typedef unsi ...
- Heap堆分析(堆转储、堆分析)
一.堆直方图 减少内存使用时一个重要目标,在堆分析上最简单的方法是利用堆直方图.通过堆直方图我们可以快速看到应用内的对象数目,同时不需要进行完整的堆转储(因为堆转储需要一段时间来分析,而且会消耗大量磁 ...
- 服务网关zuul之二:过滤器--请求过滤执行过程(源码分析)
Zuul的核心是一系列的过滤器,这些过滤器可以完成以下功能: 身份认证与安全:识别每个资源的验证要求,并拒绝那些与要求不符的请求. 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生成 ...
- Java-Runoob-高级教程-实例-方法:05. Java 实例 – 阶乘
ylbtech-Java-Runoob-高级教程-实例-方法:05. Java 实例 – 阶乘 1.返回顶部 1. Java 实例 - 阶乘 Java 实例 一个正整数的阶乘(英语:factoria ...
- linux上安装telnet服务
[LINUX] 使用yum 安装.开启 telnet 服务 pasting 一.安装telnet 1.检测telnet-server的rpm包是否安装 [root@localhost ~]# rpm ...
- hadoop集群部署
1) 安装jdk 下载jdk-6u21-linux-i586.bin 然后修改/etc/profile: export JAVA_HOME=/usr/local/jdk export CLASSPAT ...
- centos7.0KVM虚拟化
需要在图形化界面完成实验 查看CPU信息 # cat /proc/cpuinfo centos7默认安装的虚拟化包 # yum list open*tools 如果没安装就安装 #yum instal ...