?
基礎文檔:[Workerman · ThinkPHP5.0完全開發手冊 · 看云](http://www.hmoore.net/manual/thinkphp5/235128 "Workerman · ThinkPHP5.0完全開發手冊 · 看云")
在線測試地址:[EasySwoole-WebSocket在線測試工具](http://www.easyswoole.com/wstool.html "EasySwoole-WebSocket在線測試工具")
一、安裝擴展包? ?composer require topthink/think-worker??
遇到報錯:不能安裝,參考:[tp5 workerman安裝不上解決方法 - 知乎](https://zhuanlan.zhihu.com/p/127921818 "tp5 workerman安裝不上解決方法 - 知乎")?
直接執行:composer require topthink/think-worker=1.0.\*? ? ?即可成功
二、新建 server.php??
~~~php
#!/usr/bin/env php
<?php
define('APP_PATH', __DIR__ . '/application/');
define('BIND_MODULE','push/Worker');
// 加載框架引導文件
require __DIR__ . '/thinkphp/start.php';
~~~

三、新建Worker.php? ??php think make:controller push/Worker? ?即可,將里面的內容替換如下所示:
~~~php
<?php
namespace app\push\controller;
use think\Controller;
use think\Request;
use think\worker\Server;
use think\Cache;
class Worker extends Server
{
protected $socket = 'websocket://0.0.0.0:2346';
protected $processes = 1;
protected $uidConnections = array();
static $count = 0;
/**
* 收到信息
* @param $connection
* @param $data
*/
public function onMessage($connection, $data)
{
$retdata=json_decode($data,true);
$uid=$retdata['id'];
$message=$retdata['msg'];
if(isset($this->uidConnections[$uid]))
{
$connection = $this->uidConnections[$uid];
$connection->send($message);
// return true;
}
$connection->send('我收到你的信息了333='.$retdata['msg']);
}
/**
* 當連接建立時觸發的回調函數
* @param $connection
*/
public function onConnect($connection)
{
$this->uidConnections[$connection->id] = $connection;
$connection->send('你連接了我='.$connection->id);
}
// 針對uid推送數據
public function sendMessageByUid($uid, $message)
{
if(isset($this->uidConnections[$uid]))
{
$connection = $this->uidConnections[$uid];
$connection->send($message);
return true;
}
return false;
}
/**
* 當連接斷開時觸發的回調函數
* @param $connection
*/
public function onClose($connection)
{
}
/**
* 當客戶端的連接上發生錯誤時觸發
* @param $connection
* @param $code
* @param $msg
*/
public function onError($connection, $code, $msg)
{
echo "error $code $msg\n";
}
/**
* 每個進程啟動
* @param $worker
*/
public function onWorkerStart($worker)
{
}
}
~~~

~~~html
四、執行 php server.php start 遇到禁用函數就去對應的PHP里面把禁用函數刪除 (此命令可以放到Supervisor的守護進程里面去),并且查看端口是否運行,寶塔里面也要放行對應的端口 2346
~~~

配置安全組參考:?[回答阿里云websocket配置問題\_慕課手記](https://www.imooc.com/article/72220 "回答阿里云websocket配置問題_慕課手記")? ? 這個很關鍵
測試遠程連接:[http://www.voidcn.com/article/p-nifcqskk-buc.html](http://www.voidcn.com/article/p-nifcqskk-buc.html "http://www.voidcn.com/article/p-nifcqskk-buc.html")? ? ? ?telnet localhost 2346? ? ? ? ?localhost改成外網ip即可,這個走通了,前端就能直接連接了
linux 退出Telnet命令? ??先輸入命令:CTRL+\]然后再輸入命令:quit
五、前端代碼
~~~html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Title</title>
</head>
<body>
<script>
ws = new WebSocket("ws://118.**.***.207:2346");
ws.onopen = function() {
console.log("連接成功");
ws.send('tom');
console.log("給服務端發送一個字符串:tom");
};
ws.onmessage = function(e) {
console.log("收到服務端的消息:" + e.data);
};
</script>
</body>
</html>
~~~

# l
六、前端開兩個端口即可進行相互通訊:
~~~javascript
ws.send('{"id":"2","msg":"21111111111110"}');
~~~

最終效果如下所示:
?編輯?編輯
重點在這:因為在這里需要用到服務端給客戶端推送,用到了text服務
## WorkerMan中php后端及時推送消息給客戶端
參考連接:[WorkerMan中php后端及時推送消息給客戶端-Workerman-PHP中文網](https://www.php.cn/workerman/442367.html "WorkerMan中php后端及時推送消息給客戶端-Workerman-PHP中文網")
php后端及時推送消息給客戶端
原理:
1、建立一個websocket Worker,用來維持客戶端長連接
2、websocket Worker內部建立一個text Worker
3、websocket Worker 與 text Worker是同一個進程,可以方便的共享客戶端連接
4、某個獨立的php后臺系統通過text協議與text Worker通訊
5、text Worker操作websocket連接完成數據推送
代碼及步驟
~~~php
push.php
<?php
use Workerman\Worker;
require_once './vendor/workerman/workerman/Autoloader.php';
// 初始化一個worker容器,監聽1234端口
$worker = new Worker('websocket://0.0.0.0:1234');//
/*
* 注意這里進程數必須設置為1,否則會報端口占用錯誤
* (php 7可以設置進程數大于1,前提是$inner_text_worker->reusePort=true)
*/
$worker->count = 1;
// worker進程啟動后創建一個text Worker以便打開一個內部通訊端口
$worker->onWorkerStart = function($worker)
{
// 開啟一個內部端口,方便內部系統推送數據,Text協議格式 文本+換行符
$inner_text_worker = new Worker('text://0.0.0.0:5678');
$inner_text_worker->onMessage = function($connection, $buffer)
{
// $data數組格式,里面有uid,表示向那個uid的頁面推送數據
$data = json_decode($buffer, true);
$uid = $data['uid'];
// 通過workerman,向uid的頁面推送數據
$ret = sendMessageByUid($uid, $buffer);
// 返回推送結果
$connection->send($ret ? 'ok' : 'fail');
};
// $connection->send('你好,你連接我了');
// ## 執行監聽 ##
$inner_text_worker->listen();
};
// 新增加一個屬性,用來保存uid到connection的映射
$worker->uidConnections = array();
// 當有客戶端發來消息時執行的回調函數
$worker->onMessage = function($connection, $data)
{
$data=json_decode($data,true);
$connection->send('99897');
global $worker;
// 判斷當前客戶端是否已經驗證,既是否設置了uid
if(!isset($connection->uid))
{
// 沒驗證的話把第一個包當做uid(這里為了方便演示,沒做真正的驗證)
$connection->uid = $data['id'];
/* 保存uid到connection的映射,這樣可以方便的通過uid查找connection,
* 實現針對特定uid推送數據
*/
$worker->uidConnections[$connection->uid] = $connection;
$connection->send('9980'.$data['msg']);
return;
}else{
$connection->send('998123');
}
};
// 當有客戶端連接斷開時
$worker->onClose = function($connection)
{
global $worker;
if(isset($connection->uid))
{
// 連接斷開時刪除映射
unset($worker->uidConnections[$connection->uid]);
}
};
// 向所有驗證的用戶推送數據
function broadcast($message)
{
global $worker;
foreach($worker->uidConnections as $connection)
{
$connection->send($message);
}
}
// 針對uid推送數據
function sendMessageByUid($uid, $message)
{
global $worker;
if(isset($worker->uidConnections[$uid]))
{
$connection = $worker->uidConnections[$uid];
$connection->send($message);
return true;
}
return false;
}
// 運行所有的worker
Worker::runAll();
啟動后端服務 php push.php start -d
前端接收推送的js代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Title</title>
</head>
<body>
<script>
var ws = new WebSocket('ws://118.**.**.207:1234');
ws.onopen = function(){
var uid = 'uid1';
ws.send(uid);
console.log("給服務端發送一個字符串:"+uid);
};
ws.onmessage = function(e){
// alert(e.data);
console.log("收到服務端的消息:" + e.data);
};
</script>
</body>
</html>
后端推送消息的代碼
// 建立socket連接到內部推送端口
$client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
// 推送的數據,包含uid字段,表示是給這個uid推送
$data = array('uid'=>'uid1', 'percent'=>'88%');
// 發送數據,注意5678端口是Text協議的端口,Text協議需要在數據末尾加上換行符
fwrite($client, json_encode($data)."\n");
// 讀取推送結果
echo fread($client, 8192);
~~~

后端推送消息的代碼和push.php監聽同一個端口
push.php和前端監聽同一個websocket端口
通過后端推送消息的代碼向push.php推送數據,
push.php接受到數據后通過處理 利用websocket往前端推送數據
參考:
[WorkerMan中php后端及時推送消息給客戶端](https://www.php.cn/workerman/442367.html "WorkerMan中php后端及時推送消息給客戶端")
[workerman 內部系統推送數據](https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=baidu&wd=workerman%20%20%E5%86%85%E9%83%A8%E7%B3%BB%E7%BB%9F%E6%8E%A8%E9%80%81%E6%95%B0%E6%8D%AE&oq=php%2520%25E8%25BF%259E%25E6%258E%25A5websocket%2520%25E5%258F%2591%25E9%2580%2581%25E6%25B6%2588%25E6%2581%25AF&rsv_pq=ad92a8a1000d2a5c&rsv_t=e510BtJ8mcMjXrby2cxwKlWpOqVkeKijK0iPv%2FBLWnxZSEO6u1pQGrcICIA&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_btype=t&inputT=12542&rsv_sug3=97&rsv_sug1=64&rsv_sug7=100&rsv_sug2=0&rsv_sug4=13298 "workerman 內部系統推送數據")
[Centos7開放端口及查看端口](https://www.cnblogs.com/heqiuyong/p/10460150.html "Centos7開放端口及查看端口")
?
?
- 支付寶身份驗證接口踩坑實錄-PHP(基于ThinkPHP5)(第二版更新中)
- 抖音小程序開發之授權登錄+支付寶支付+微信支付(ThinkPHP5-第三版修訂中)
- TP5小知識點錦集(長期更新)
- PHP 二維碼生成+識別
- 高德地圖點聚合點擊事件以及內容渲染
- ThinkPhP5使用phpexcle 導出數據(復制粘貼就可使用)
- Fastadmin微信小程序授權登錄+獲取手機號插件
- PHP -AES-128-CBC位加密解密
- PHP-Rsa分段加密解密(ThinkPHP5)
- PHP大轉盤抽獎代碼片段
- Fastadmin 項目上線關閉調試模式注意事項(記一次require-table.js修改事件)
- ThinkPHP5條件查詢FIND_IN_SET正反使用
- ThinkPhP5整合微信小程序訂閱消息
- think-queue處理延時任務事件
- ThinkPHP5 生成二維碼
- Python3定時監控指定文件內容變換-(增加多行,遍歷每行進行邏輯分析處理)
- Python3開發聲光報警器監控觸發報警
- ThinkPHP5下載文件流到本地
- 百度鷹眼抽軌跡集合稀算法&縮放比例調整顯示靜態圖(ThinkPHP5)
- PHP 導出Excle
- Fastadmin 自定義Tab選項卡(B表的條件查詢A表的數據,在A表里面加B表的參數作為選項卡)
- Fastadmin 修改url組件跳轉為復制功能
- 微信H5分享好友跟朋友圈-基于Easywechat
- Python3抓取監控日志文件關鍵詞跟內容變化修正版
- ThinkPHP5上傳圖片壓縮處理-(解決IOS拍照上傳旋轉90度問題)最近更新2021年12月9日11:35:07
- 二維數組根據‘key’分組為新的三維數組
- ThinkPHP5 成功部署Workerman 運行示例
- Fastadmin框架TOKEN的使用
- ThinkPHP5 -微信小程序訂閱消息開發-插件(插件基于fastadmin開發)
- ThinkPHP5-文本轉義emoji表情
- ThinkPHP5 自定義命令行處理 監聽Redis key失效觸發回調事件,實現延遲任務 實現自動取消訂單,自動完成訂單
- Fastadmin插件Shopro商城里面短信插件修改為騰訊云短信插件步驟
- Fastadmin框架自定義搜索操作流程
- ThinkPHP5 處理 微信小程序內容安全審核
- Fastadmin自定義快捷搜索之模糊搜索關聯他表
- php根據年月獲取指定月份天數及日期數組的方法
- PHP構造函數使用校驗token
- 基于ThinkPHP5&Redis騰訊云短信驗證碼注冊登錄基礎業務邏輯代碼整合
- ThinkPHP 解決跨域問題
- 支付寶沙箱環境測試支付(好久沒做都忘了,寫個博客比較省事)
- ThinkPHP5生成抖音小程序帶參數二維碼
- ThinkPHP5導入Excle-簡單絲滑
- PHP生成帶參數的小程序二維碼
- ThinkPHP5成功調通IOS蘋果支付
- swoole寫聊天室,簡單粗暴
- 微信小程序內容安全鑒別的時候,不成功因為沒有轉碼
- Fastadmin 后臺Excle文件上傳(更新新增功能)
- Lnmp 配置thinkphp5 Nginx基礎設置,包含http+https配置
- 通過經緯度獲取數據庫信息自動計算地址距離遠近
- 二維數組根據某個字段排序
- PHP二維數組去重,最簡單的方法
- TP5微信redis列隊群發模板消息Sendmsg
- PHP檢測是否關注公眾號,親測可用
- 小程序推廣分享帶參數二維碼生成
- 基于ThinkPHP5微信H5授權登錄獲取用戶信息(改進版)
- php過濾微信昵稱中的表情
- Socket.io