tp5+workman(GatewayWorker) 安装及使用
一、安装thinkphp5
1、宝塔删除php禁用函数putenv、pcntl_signal_dispatch、pcntl_wai、pcntl_signal、pcntl_alarm、pcntl_fork,执行安装命令。
composer create-project topthink/think=5.0.* tp5 --prefer-dist

2、配置好站点之后,浏览器打开访问成功。

二、tp5安装GatewayWorker
1、进入tp5目录,安装GatewayWorker
composer require workerman/gateway-worker
如果报错安装指定版本
2、安装workman
composer require workerman/workerman
如果报错安装指定版本
3、安装gatewayclient
composer require workerman/gatewayclient
如果报错安装指定版本
三、使用GatewayWorker
注:我已修改默认端口号,在宝塔开启端口号
1、创建文件 tp5/public/start.php
<?php
/*** run with command* php start.php start*/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,以便启动所有服务 application更改为自己文件夹名字,我的为websocket
foreach(glob(__DIR__.'/../api/websocket/start*.php') as $start_file)
{require_once $start_file;
}
// 运行所有服务
Worker::runAll();
2、创建文件 tp5/api/Socket/Events.php (创建php文件,或者下载demo复制过去即可)
<?php
/*** This file is part of workerman.** Licensed under The MIT License* For full copyright and license information, please see the MIT-LICENSE.txt* Redistributions of files must retain the above copyright notice.** @author walkor<walkor@workerman.net>* @copyright walkor<walkor@workerman.net>* @link http://www.workerman.net/* @license http://www.opensource.org/licenses/mit-license.php MIT License*//*** 用于检测业务代码死循环或者长时间阻塞等问题* 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload* 然后观察一段时间workerman.log看是否有process_timeout异常*/
//declare(ticks=1);use \GatewayWorker\Lib\Gateway;/*** 主逻辑* 主要是处理 onConnect onMessage onClose 三个方法* onConnect 和 onClose 如果不需要可以不用实现并删除*/
class Events
{/*** 当客户端连接时触发* 如果业务不需此回调可以删除onConnect* * @param int $client_id 连接id*/public static function onConnect($client_id){echo "【新的客户端链接】:client_id:".$client_id.PHP_EOL;// 向当前client_id发送数据 Gateway::sendToClient($client_id, "Hello $client_id\r\n");// 向所有人发送Gateway::sendToAll("$client_id login\r\n");}/*** 当客户端发来消息时触发* @param int $client_id 连接id* @param mixed $message 具体消息*/public static function onMessage($client_id, $message){// 向所有人发送 Gateway::sendToAll("$client_id said $message\r\n");}/*** 当用户断开连接时触发* @param int $client_id 连接id*/public static function onClose($client_id){// 向所有人发送 GateWay::sendToAll("$client_id logout\r\n");}
}
3、创建文件tp5/application/Socket/start_businessworker.php
<?php
/*** This file is part of workerman.** Licensed under The MIT License* For full copyright and license information, please see the MIT-LICENSE.txt* Redistributions of files must retain the above copyright notice.** @author walkor<walkor@workerman.net>* @copyright walkor<walkor@workerman.net>* @link http://www.workerman.net/* @license http://www.opensource.org/licenses/mit-license.php MIT License*/
use Workerman\Worker;
use Workerman\WebServer;
use GatewayWorker\Gateway;
use GatewayWorker\BusinessWorker;
use Workerman\Autoloader;// 自动加载类
require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/Events.php';// bussinessWorker 进程
$worker = new BusinessWorker();
// worker名称
$worker->name = 'YourAppBusinessWorker';
// bussinessWorker进程数量
$worker->count = 4;
// 服务注册地址
$worker->registerAddress = '127.0.0.1:23222';//这行代码防止出现报错:Waring: Events::onMessage is not callable
$worker->eventHandler = 'Events';// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{Worker::runAll();
}
4、创建文件tp5/application/Socket/start_gateway.php
<?php
/*** This file is part of workerman.** Licensed under The MIT License* For full copyright and license information, please see the MIT-LICENSE.txt* Redistributions of files must retain the above copyright notice.** @author walkor<walkor@workerman.net>* @copyright walkor<walkor@workerman.net>* @link http://www.workerman.net/* @license http://www.opensource.org/licenses/mit-license.php MIT License*/
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:24222");
// gateway名称,status方便查看
$gateway->name = 'moods';
// 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:23222';// 心跳间隔
//$gateway->pingInterval = 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();
}
5、创建文件tp5/application/Socket/start_register.php
<?php
/*** This file is part of workerman.** Licensed under The MIT License* For full copyright and license information, please see the MIT-LICENSE.txt* Redistributions of files must retain the above copyright notice.** @author walkor<walkor@workerman.net>* @copyright walkor<walkor@workerman.net>* @link http://www.workerman.net/* @license http://www.opensource.org/licenses/mit-license.php MIT License*/
use \Workerman\Worker;
use \GatewayWorker\Register;// 自动加载类
require_once __DIR__ . '/../../vendor/autoload.php';// register 必须是text协议
$register = new Register('text://0.0.0.0:23222');// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{Worker::runAll();
}
6、启动websocket程序
1、防火墙打开8282、1236端口,执行下面命令
//运行php start.php start//linux运行php start.php start -d//停止php start.php stop//检测端口是否以被占用
netstat -an | grep 80//关闭某个进程
sudo kill -9 进程ID如果修改文件后一定要先停止在运行一下文件,否则不生效
四、使用GatewayWorker发布广播
1、创建文件tp5/application/index/controller/Index.php,执行这个方法就可以向所有人发布广播了。
<?php
namespace app\index\controller;
use GatewayClient\Gateway;
class Index
{public function index(){Gateway::sendToAll(" index发的消息 \r\n");}
}
后面逻辑,自己处理即可
测试发信息内容为
测试地址: http://www.jsons.cn/websocket/
用户1
用户2

下面是我写的一个例子
数据库:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for cmf_chat
-- ----------------------------
DROP TABLE IF EXISTS `cmf_chat`;
CREATE TABLE `cmf_chat` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_ids` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用于查找聊天记录',`operation_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作类型:send_message发送信息,login登录',`send_uid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发送人',`send_client_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`to_uid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收信息人',`to_client_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`openid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'openid',`content_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发送信息类型:text文本',`content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发送信息',`signature` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '唯一签名',`date` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '日期',`time` bigint(20) NULL DEFAULT NULL COMMENT '时间',`create_time` bigint(20) NULL DEFAULT NULL COMMENT '创建时间',`update_time` bigint(20) NULL DEFAULT NULL COMMENT '更新时间',`delete_time` bigint(20) NULL DEFAULT 0 COMMENT '软删除',`me_client_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 100 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '存入聊天记录' ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of cmf_chat
-- ----------------------------SET FOREIGN_KEY_CHECKS = 1;
1.安装mysql,插架
使用workerman/mysql 扩展
composer require workerman/mysql
2.处理逻辑 Events.php
<?php
/*** This file is part of workerman.** Licensed under The MIT License* For full copyright and license information, please see the MIT-LICENSE.txt* Redistributions of files must retain the above copyright notice.** @author walkor<walkor@workerman.net>* @copyright walkor<walkor@workerman.net>* @link http://www.workerman.net/* @license http://www.opensource.org/licenses/mit-license.php MIT License*//*** 用于检测业务代码死循环或者长时间阻塞等问题* 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload* 然后观察一段时间workerman.log看是否有process_timeout异常*///declare(ticks=1);use \GatewayWorker\Lib\Gateway;/*** 主逻辑* 主要是处理 onConnect onMessage onClose 三个方法* onConnect 和 onClose 如果不需要可以不用实现并删除*/error_reporting(0);class Events
{/*** 新建一个类的静态成员,用来保存数据库实例*/public static $db = null;/*** 进程启动后初始化数据库连接 两者都可以*/public static function onWorkerStart($worker){//使用gateway_worker扩展self::$db = new \GatewayWorker\Lib\DbConnection('47.****.188', '3306', 'kf***od_com', 'Gyt***4jb65cD', 'kf***d_com');//使用workerman/mysql 扩展// self::$db = new \Workerman\MySQL\Connection('host', 'port', 'user', 'password', 'db_name');}/*** 当客户端连接时触发* 如果业务不需此回调可以删除onConnect** @param int $client_id 连接id*/public static function onConnect($client_id){// 向当前client_id发送数据$restult = ['operation_type' => 'login','me_client_id' => $client_id,'content_type' => "text",'content' => "$client_id login success",'signature' => cmf_random_string(100),'date' => date('Y-m-d H:i:s'),'time' => time(),'create_time' => time(),];//存入数据库self::$db->insert('cmf_chat')->cols($restult)->query();//转换为json格式$send_message = json_encode($restult, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);//给自己发送注册成功Gateway::sendToClient($client_id, $send_message);// 向所有人发送//Gateway::sendToAll("$client_id login\r\n");}/*** 当客户端发来消息时触发* @param int $client_id 连接id* @param mixed $message 具体消息*/public static function onMessage($client_id, $message){//写个日志文件$contents = json_encode($message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);//写入日志$filename = '../api/websocket/log/';!is_dir($filename) && mkdir($filename, 0755, true);$file_hwnd = fopen($filename . date('Y-m-d') . ".log", "a+");fwrite($file_hwnd, "$client_id----$contents" . "\r\n");fclose($file_hwnd);//数据格式转为数组$message = json_decode($message, true);// 向指定人发送$restult = ['operation_type' => 'send_message','send_client_id' => isset($message['send_client_id']) ? $message['send_client_id'] : '',//用户client_id'send_uid' => isset($message['send_uid']) ? $message['send_uid'] : '',//或者用户uid'to_client_id' => isset($message['to_client_id']) ? $message['to_client_id'] : '','to_uid' => isset($message['to_uid']) ? $message['to_uid'] : '','openid' => isset($message['openid']) ? $message['openid'] : '','content_type' => "text",'content' => $message['content'],'signature' => cmf_random_string(100),'date' => date('Y-m-d H:i:s'),'time' => time(),'create_time' => time(),];//存入数据库self::$db->insert('cmf_chat')->cols($restult)->query();//转换为json格式$send_message = json_encode($restult, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);//给指定人发信息if ($restult['to_client_id']) Gateway::sendToClient($restult['to_client_id'], $send_message);if ($restult['to_uid']) Gateway::sendToUid($restult['to_uid'], $send_message);//在给自己信息同步一下if ($restult['send_client_id']) Gateway::sendToClient($restult['send_client_id'], $send_message);if ($restult['send_uid']) Gateway::sendToUid($restult['send_uid'], $send_message);//向所有人发送//Gateway::sendToAll("$send_message content\r\n");}/*** 当用户断开连接时触发* @param int $client_id 连接id*/public static function onClose($client_id){// 向所有人发送//GateWay::sendToAll("$client_id logout\r\n");}/*** 发送请求,将数据存入数据库中* @param $url* @param $data*/public function add_chat($url, $data){$ch = curl_init($url);curl_setopt($ch, CURLOPT_POST, 1);curl_setopt($ch, CURLOPT_POSTFIELDS, $data);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$response = curl_exec($ch);// if ($response === false) {// echo 'Curl error: ' . curl_error($ch);// } else {// echo 'Response: ' . $response;// }curl_close($ch);}}
3.前端例子
<!DOCTYPE html>
<html><head><title>WebSocket Example</title><script>// 创建WebSocket连接 var socket = new WebSocket("ws://47.94.223.188:24222");// 连接打开时触发的事件处理函数 socket.onopen = function(event) {console.log("连接已建立");};// 发送消息到服务器 function sendMessage() {var messageInput = document.getElementById("message");var message = messageInput.value;//获取自己的client_idvar me_client_id = document.getElementById("me_client_id").value;//发送信息 var send_message = {'operation_type': 'send_message','send_client_id': me_client_id,//'send_uid': me_client_id,'to_uid': 'w001', 'openid': 1,'content_type': 'text','content': message,}const jsonString = JSON.stringify(send_message);socket.send(jsonString);// messageInput.value = "";}// 接收到消息时触发的事件处理函数 socket.onmessage = function(event) {var messageContainer = document.getElementById("message-container");var messageElement = document.createElement("p");//返回数据&处理成数组格式var result = event.data;var jsonObject = JSON.parse(result);//如果类型为 operation_type==login 存一下me_client_idif (jsonObject['operation_type'] == 'login') {var me_client_id = document.getElementById("me_client_id");me_client_id.value = jsonObject.me_client_id;}messageElement.textContent = event.data;messageContainer.appendChild(messageElement);};// 连接关闭时触发的事件处理函数 socket.onclose = function(event) {console.log("连接已关闭");};// 连接发生错误时触发的事件处理函数 socket.onerror = function(error) {console.error("WebSocket 错误: " + error);};</script></head><body><h1>WebSocket Example</h1><input type="text" id="me_client_id"><input type="text" id="message"><button onclick="sendMessage()">发送</button><div id="message-container"></div></body>
</html>
4.拿到client_id 绑定uid
/*** 获取所有在线人数* @return array* https://kf1***om/api/wxapp/send/get_all_uid_list*/public function get_all_uid_list(){$restult = Gateway::getAllUidList();dump($restult);exit();}/*** client_id与uid绑定* 传入自己的client_id和openid,自动绑定为w+用户id 例如w1,w2,w100005* @return array* https://kf****om/api/wxapp/send/bind_uid*/public function bind_uid(){$client_id = '7f0000010b5400000004';$uid = 'w002';Gateway::bindUid($client_id, $uid);dump(cmf_random_string(100, 3));exit();}
相关文章:
tp5+workman(GatewayWorker) 安装及使用
一、安装thinkphp5 1、宝塔删除php禁用函数putenv、pcntl_signal_dispatch、pcntl_wai、pcntl_signal、pcntl_alarm、pcntl_fork,执行安装命令。 composer create-project topthink/think5.0.* tp5 --prefer-dist 2、配置好站点之后,浏览器打开访问成…...
vscode安装Prettier插件,对vue3项目进行格式化
之前vscode因为安装了Vue Language Features (Volar)插件,导致Prettier格式化失效,今天有空,又重新设置了一下 1. 插件要先安装上 2. 打开settings.json {"editor.defaultFormatter": "esbenp.prettier-vscode","…...
macOS跨进程通信: XPC 创建实例
一:简介 XPC 是 macOS 里苹果官方比较推荐和安全的的进程间通信机制。 集成流程简单,但是比较绕。 主要需要集成 XPC Server 这个模块,这个模块最终会被 apple 的根进程 launchd 管理和以独立进程的方法唤起和关闭, 我们主app 进…...
Ubuntu18.04 升级Ubuntu20.04
文章目录 背景升级方法遇到的问题 背景 因项目环境需要,欲将Ubuntu18.04升级至Ubuntu20.04,参考网上其他小伙伴的方法,也遇到了一个问题,特此记录一下,希望能帮助其他有同样问题的小伙伴。 升级方法 参考:…...
自动化测试怎么做?看完你就懂了。。。
前言 我想应该有很多测试人员应该有这样的疑虑,自动化测试要怎么去做,现在我把自己的一些学习经验分享给大家,希望对你们有帮助,有说的不好的地方,还请多多指教! 对于测试人员来说,不管进行功…...
小秋SLAM入门实战opencv所有文章汇总
opencv_core和 opencv_imgcodecs是 OpenCV(开源计算机视觉库)的两个主要模块 【如何使用cv::erode()函数对图像进行腐蚀操作】 头文件用途 用OpenCV创建一张类型为CV_8UC1的单通道随机灰度图像 用OpenCV创建一张灰度黑色图像并设置某一列为白色 OpenCV创…...
2023年终总结(脚踏实地,仰望星空)
回忆录 2023年,经历非常多的大事情,找工作、实习、研究生毕业、堂哥结婚、大姐买车、申博、读博、参加马拉松,有幸这一年全家人平平安安,在稳步前进。算是折腾的一年,杭州、赣州、武汉、澳门、珠海、遵义来回跑。完成…...
Transforer逐模块讲解
本文将按照transformer的结构图依次对各个模块进行讲解: 可以看一下模型的大致结构:主要有encode和decode两大部分组成,数据经过词embedding以及位置embedding得到encode的时输入数据 输入部分 embedding就是从原始数据中提取出单词或位置&…...
macOS进程间通信的常用技术汇总
macOS进程间通信的常用技术汇总 命令行传参。yyds管道(pipe), 匿名管道, c的技术,可以跨平台使用 只能在父子进程间通信,由于是单向的管道,只能单方面传输数据。 如果需要双向传输,需要建立双向的两条管道才行 匿名管…...
高德地图信息窗体设置
1. 添加默认信息窗体 //构建信息窗体中显示的内容var info [];info.push(<div style"height: 36px; line-height: 45px; padding: 0px 20px; white-space:nowrap;">位置:北京</div>);info.push(<div style"height: 36px; line-heig…...
isEmpty 和 isBlank 的用法区别,居然一半的人答不上来.....
isEmpty 和 isBlank 的用法区别 isEmpty系列isBank系列 hi!我是沁禹~ 也许你两个都不知道,也许你除了isEmpty/isNotEmpty/isNotBlank/isBlank外,并不知道还有isAnyEmpty/isNoneEmpty/isAnyBlank/isNoneBlank的存在, come on ,让我们一起来探索org.apache…...
数据分析求职-简历准备
简历在整个求职过程中的重要性不言而喻,今天咱们来聊求职过程中简历准备的那些事儿~ 1. 简历究竟有啥用 求职的流程简单说就是:网申->笔试->面试->offer 其中网申环节,简历100%决定了你的通过与否,这个点大家都知道。…...
亚马逊店铺遇到账号申诉模版分享
1.表达诚意,先认错再说:我知道,最近我们在Amazon.com上作为卖家的表现已经低于亚马逊和我们自己的质量标准。 2.清楚分明的格式:我们库存管理的混乱导致了延迟发货,更糟糕的是,物品无法使用。当延迟发货和…...
2023年广东省网络安全A模块(笔记详解)
模块A 基础设施设置与安全加固 一、项目和任务描述: 假定你是某企业的网络安全工程师,对于企业的服务器系统,根据任务要求确保各服务正常运行,并通过综合运用登录和密码策略、流量完整性保护策略、事件监控策略、防火墙策略等多…...
竞赛保研 基于机器视觉的银行卡识别系统 - opencv python
1 前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学习的银行卡识别算法设计 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng…...
书摘:C 嵌入式系统设计模式 04
本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。 本系列描述我对书中内容的理解。 实现类的最简单方法是使用文件作为封装…...
C 练习实例16 - 最大公约数和最小公倍数
题目:输入两个正整数a和b,求其最大公约数和最小公倍数 数学:最大公约数*最小公倍数a*b 例如:a16,b20。最小公倍数80,最大公约数4。80*416*20。 算法:辗转相除法,又称欧几里德算法…...
GAN-概念和应用场景
概念和应用 生成对抗网络 (GAN) 的 18 个令人印象深刻的应用 by 杰森布朗利 on July 12, 2019 in 生成对抗网络110 鸣叫 共享 生成对抗网络 (GAN) 是一种用于生成建模的神经网络架构。 生成式建模涉及使用模型生成可…...
LeetCode(36)有效的数独 ⭐⭐
请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图) 注…...
用LCD显示字符‘A‘
#include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 sbit RSP2^0; //寄存器选择位,将RS位定义为P2.0引脚 sbit RWP2^1; //读写选择位,将RW位定义为P2.1引脚 sbit EP2^2; //使能…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
