- 卷积神经网络学习笔记——ZFNet(Tensorflow实现)
- 24年3月使用VS22编译TelegramDesktop
- STM32中RFID模块(MFRC522)简单应用
- java反序列化-CC1
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛,就离不开通讯了,然后我就想到了长连接。这里本人用的是GatewayWorker框架.
GatewayWorker是基于Workerman开发的一套TCP长连接的应用框架,实现了单发、群发、广播等接口,内置了mysql类库,GatewayWorker分为Gateway进程和Worker进程,支持分布式部署,能够支持大量的连接数.
1、启动所有进程(GatewayWorker、business、register)
2、GatewayWorker和business进程启动后向register请求注册
3、register服务收到注册请求后,把所有Gateway的通讯地址保存在内存中同时把内存中所有的Gateway的通讯地址发给business
4、business进程得到所有的Gateway内部通讯地址后进行连接GatewayWorker
5、如果有新的GatewayWorker服务进行register,则将新的Gateway内部通讯地址列表将广播给所有buiness并建立连接
6、如果有GatewayWorker下线,则Register服务会收到通知,会将该GatewayWorker内部通讯地址删除,然后广播新的内部通讯地址列表给所有business
7、此时GatewayWorker与buiness已经建立起长连接
8、客户端的事件及接受的数据全部由GatewayWorker转发给business进行处理。
├── Applications // 项目应用目录
│ └── YourAppGateway // 建立一个存放workman的目录,名字随意
│ ├── Events.php // 处理主逻辑业务的文件,管理onConnect onMessage onClose 等方法
│ ├── start_gateway.php // gateway进程启动脚本、配置服务注册地址、端口号、进程数等参数
│ ├── start_businessworker.php // 用户进程的启动脚本
│ └── start_register.php // 注册服务的启动脚本
│
├── start.php // 全局启动脚本,此脚本会依次加载Applications/YourAppGateway/start*.php对所有脚本进行启动
│
└── vendor // GatewayWorker框架和Workerman框架源码目录
以宝塔为例 。
登录SSH终端,使用以下命令下载Composer的安装脚本:
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
运行下面的命令来安装Composer:
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
检查composer版本 。
composer -v //检查composer版本
在项目根目录打开宝塔终端,输入以下命令安装workman 。
composer require topthink/think-worker
在项目根目录打开宝塔终端,输入以下命令安装GatewayWorker 。
composer require workerman/gateway-worker
可以选择官方提供的demo 链接:http://www.workerman.net/download/GatewayWorker.zip 。
或者使用我根据demo改编而来的 。
先在项目应用目录(一般是Applications)下新建一个文件存储以下四个进程文件 。
start_gateway.php 。
<?php
use \Workerman\Worker;
use \Workerman\WebServer;
use \GatewayWorker\Gateway;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;
// 自动加载类
require_once __DIR__ . '/../../vendor/autoload.php';
// gateway 进程,这里使用Text协议,可以用telnet测试
$gateway = new Gateway("websocket://0.0.0.0:8283");
// gateway名称,status方便查看
$gateway->name = 'YourAppGateway';
// gateway进程数
$gateway->count = 200;
// 本机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:1237';
// 心跳间隔
//$gateway->pingInterval = 10;
// 心跳数据
//$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();
}
start_businessworker.php 。
<?php
use Workerman\Worker;
use Workerman\WebServer;
use GatewayWorker\Gateway;
use GatewayWorker\BusinessWorker;
use Workerman\Autoloader;
// 自动加载类
require_once __DIR__ . '/../../vendor/autoload.php';
// bussinessWorker 进程
$worker = new BusinessWorker();
// worker名称
$worker->name = 'YourAppBusinessWorker';
// bussinessWorker进程数量
$worker->count = 200;
// 服务注册地址、端口
$worker->registerAddress = '127.0.0.1:1237';
// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}
start_register.php 。
<?php
use \Workerman\Worker;
use \GatewayWorker\Register;
// 自动加载类
require_once __DIR__ . '/../../vendor/autoload.php';
// register 必须是text协议 1237为端口
$register = new Register('text://0.0.0.0:1237');
// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}
Events.php 。
<?php
use \GatewayWorker\Lib\Gateway;
/**
* 主逻辑
* 主要是处理 onConnect onMessage onClose 三个方法
*/
class Events
{
/**
* 当客户端连接时触发
*
* @param int $client_id 连接id
*/
public static function onConnect($client_id)
{
echo "【新的客户端链接】:client_id:".$client_id.PHP_EOL;
// 向当前client_id发送数据
Gateway::sendToClient($client_id, "");
// 向所有人发送
$data=[
'client_id'=>$client_id,
'message'=>'欢迎'.$client_id.'登录!',
'data'=>[]
];
Gateway::sendToAll(json_encode($data));
// Gateway::sendToAll("$client_id login\r\n");
}
/**
* 当客户端发来消息时触发
* @param int $client_id 连接id
* @param mixed $message 具体消息
*/
public static function onMessage($client_id, $message){
$data=[
'client_id'=>$client_id,
'message'=>$client_id.'说:'.$result['message'],
'data'=>$message
];
Gateway::sendToAll(json_encode($data));
// 向所有人发送
// Gateway::sendToAll("$client_id said $message\r\n");
}
/**
* 当用户断开连接时触发
* @param int $client_id 连接id
*/
public static function onClose($client_id)
{
// 向所有人发送
// GateWay::sendToAll("$client_id 退出了!\r\n");
}
}
随后在项目的根目录下新建一个启动文件 。
start_all_workman.php 。
<?php
ini_set('display_errors', 'on');
use Workerman\Worker;
if(strpos(strtolower(PHP_OS), 'win') === 0)
{
exit("start.php not support windows, please use start_for_win.bat\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('GLOBAL_START', 1);
require_once __DIR__ . '/vendor/autoload.php';
// 加载所有Applications/*/start.php,以便启动所有服务
foreach(glob(__DIR__.'/application/此处请改成你自己命名存放workman的目录名/start*.php') as $start_file)
{
require_once $start_file;
}
// 运行所有服务
Worker::runAll();
注意开启端口后记得去放行端口!!!除了宝塔放行以外,你的服务器(阿里云/腾讯云等等)也记得要去放行!!! 。
在项目根目录下打开终端,输入php start_all_workman.php start -d ,开启守护进程,如果出现一下页面即成功开启 。
如想关闭workman进程则输入php start_all_workman.php stop 进行关闭 。
如果你的网站使用的是Https协议的话,WebSocket必须使用wss协议 但是wss协议不支持IP:端口的形式,而是只能写域名+url 所以为了解决使用https协议而WebSocket不能连接的问题,可以使用Nginx进行反向代理 在网站配置文件的server下加入以下代码 。
location /connectWorkman(名字随你取,别跟其他反向代理重名就行)
{
proxy_pass http://127.0.0.1:8283;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Real-IP $remote_addr;
}
init() {
SocketTask = uni.connectSocket({
url: 'wss://chat.gdpaimaihui.com/auction', //正式
header: {
'content-type': 'application/json'
},
success: function(res) {
console.log('WebSocket连接创建', res);
},
fail: function(err) {
uni.showToast({
title: '网络异常!',
icon: 'none'
});
console.log(err);
}
});
//websocket监听事件
SocketTask.onOpen((res) => {
socketOpen = true
canReconnect = true
console.log('监听 WebSocket 连接打开事件。', res);
//websocket连接后可以启动个定时器,每隔一段时间进行心跳一次,以防心跳停止断开连接
this.timer = setInterval(() => {
SocketTask.send({
data: '心跳',
success() {
// console.log('发送心跳成功');
}
})
}, 2000)
});
SocketTask.onError((onError) => {
console.log('监听 WebSocket 错误。错误信息', onError);
socketOpen = false;
if (canReconnect) {
this.reconnect()
canReconnect = false
}
});
SocketTask.onMessage((res) => {
console.log('监听WebSocket接受到服务器的消息事件。服务器返回的消息', res);
});
},
//重新连接
reconnect() {
if (!socketOpen) {
let count = 0;
reconnectInterval = setInterval(() => {
console.log("正在尝试重连")
uni.showToast({
title: '正在尝试重连',
icon: 'none'
})
this.init();
count++
console.log();
//重连一定次数后就不再重连
if (count >= reconnectTimes) {
clearInterval(reconnectInterval)
uni.showToast({
title: '网络异常或服务器错误',
icon: 'none'
})
}
}, reconnectDelay)
}
}
上述为之前给公司做内部通讯软件时个人整理内容,水平有限,如有错误之处,望各位园友不吝赐教!如果觉得不错,请点击推荐和关注!谢谢~๑•́₃•̀๑ [鲜花][鲜花][鲜花] 。
最后此篇关于【workerman】uniapp+thinkPHP5使用GatewayWorker实现实时通讯的文章就讲到这里了,如果你想了解更多关于【workerman】uniapp+thinkPHP5使用GatewayWorker实现实时通讯的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想要改善这个问题吗?更新问题,以便将其作为on-topi
有没有办法只允许 https 而不是 http 与 Neo4j 服务器通信?另外,Neo4j Shell 的通信使用哪个 channel ,http 还是 https? 最佳答案 这来自 Neo4j
您好,我有新问题 :) 我正在构建带有面板的简单时事通讯,以向注册用户和时事通讯邮件地址发送邮件。 我有此代码,但时事通讯仅发送给注册用户。谁能告诉我为什么? $zapytanie = mys
第一次发帖,所以可能会有比必要的更多的信息,但我想彻底: 我们的 C 练习之一是创建发送器和接收器程序,通过 RS232 串行通信与零调制解调器交换数据。我们使用了虚拟端口程序(如果你想测试的话,我使
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我有一台通过 RS485 连接到另一台设备的单板计算机。计算机应向设备发送请求并接收响应(使用设备相关协议(protocol))。我可以毫无问题地发送消息并且设备接收它们(例如,我可以更改设备的参数)
我目前正在尝试在我的 Visual Basic 6 应用程序中引用 .NET COM 库。我已经使用 Regasm 注册了它,并且在我的类(class)中将 ComVisible 设置为 true。但
Closed. This question needs to be more focused 。它目前不接受答案。 想改善这个问题吗?更新问题,使其仅通过 editing this post 关注一个
我尝试通过 https 协议(protocol)在 Archiva 和 Jenkins 之间建立通信,但我收到以下错误: [WARNING] Could not transfer metadata .
我完成了一个运行良好的客户端/服务器套接字通信程序。现在我想弄清楚如何做到这一点,以便我可以同时拥有到服务器的多个客户端连接。我环顾四周,似乎有不止几种不同的方法可以做到这一点。所以我来这里是想向你们
我正在 mailchimp 中制作时事通讯,我在使用 outlook 时遇到了这个问题,它一直在干扰我的两个专栏,如图所示: 这是这部分的代码:
我正在创建一份时事通讯,经过大量努力,它在除 android 的 gmail 应用程序之外的任何地方都有效。问题是它似乎有最小字体大小,这会导致我的表格损坏。 有没有办法克服最小字体大小而不是媒体查询
C++ 作为Client端 view plaincopy to clipboardprint? 复制代码 代码如下: // Client.cpp : Defines the entry poi
我创建了 ECM NewsLetter,其中包含一些网站链接(另一个项目)。在在线版本的 NewsLetter 链接中工作正常,但是当我将此 NewsLetter 发送到我的电子邮件并尝试单击我的邮件
无论出于何种原因,我的文本大小调整在 iPhone 上无法正常工作,但在 Android 和其他电子邮件格式中工作正常。似乎看不出这两个文件之间有任何区别。图片也调整了大小,似乎只是文本的问题。
我正在开发一个网站,我需要将 HTML 新闻稿发送到邮件列表。 我构建了一个 html 框架,其中包含“在浏览器中查看”和“取消订阅”链接(原因会有所不同)。在管理模块中,我发布 html 并为 ht
我正在尝试在 B-L072Z-LRWAN(Master) 和 Arduino(Slave) 之间进行 I2C 通信。 我使用以下代码成功将数据从主站发送到从站: B-L072Z-LRWAN 代码: #
我有 ECM NewsLetter,其中包含指向站点(另一个项目)的一些链接。当我通过单击发送按钮将此时事通讯发送到我的电子邮件时 - 当我从电子邮件收件箱中单击它们时,链接不起作用。它显示 404
我是一名优秀的程序员,十分优秀!