Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统 - 八重樱 - 博客园

mikel阅读(1479)

来源: Swoole跟thinkphp5结合开发WebSocket在线聊天通讯系统 – 八重樱 – 博客园

ThinkPHP使用Swoole需要安装 think-swoole Composer包,前提系统已经安装好了Swoole PECL 拓展*

tp5的项目根目录下执行composer命令安装think-swoole:

composer require topthink/think-swoole

 

话不多说,直接上代码:

新建WebSocket.php控制器

(监听端口要确认服务器放行,宝塔环境还需要添加安全组规则)

复制代码
 1 <?php
 2  
 3 namespace app\home\controller;
 4 use think\swoole\Server;
 5 class WebSocket extends Server
 6 {
 7     protected $host = '0.0.0.0'; //监听所有地址
 8     protected $port = 9501; //监听9501端口
 9     protected $serverType = 'socket';
10     protected $option = [ 
11         'worker_num'=> 4, //设置启动的Worker进程数
12         'daemonize'    => false, //守护进程化(上线改为true)
13         'backlog'    => 128, //Listen队列长度
14         'dispatch_mode' => 2, //固定模式,保证同一个连接发来的数据只会被同一个worker处理
15  
16         //心跳检测:每60秒遍历所有连接,强制关闭10分钟内没有向服务器发送任何数据的连接
17         'heartbeat_check_interval' => 60,
18         'heartbeat_idle_time' => 600
19     ];
20  
21     //建立连接时回调函数
22     public function onOpen($server,$req)
23     {
24         $fd = $req->fd;//客户端标识
25         $uid = $req->get['uid'];//客户端传递的用户id
26         $token = $req->get['token'];//客户端传递的用户登录token
27         
28         //省略token验证逻辑......
29         if (!$token) {
30             $arr = array('status'=>2,'message'=>'token已过期');
31             $server->push($fd, json_encode($arr));
32             $server->close($fd);
33             return;
34         }
35         //省略给用户绑定fd逻辑......
36         echo "用户{$uid}建立了连接,标识为{$fd}\n";
37     }
38  
39     //接收数据时回调函数
40     public function onMessage($server,$frame)
41     {
42         $fd = $frame->fd;
43         $message = $frame->data;
44  
45         //省略通过fd查询用户uid逻辑......
46         $uid = 666;
47         $data['uid'] = $uid;
48         $data['message'] = '用户'.$uid.'发送了:'.$message;
49         $data['post_time'] = date("m/d H:i",time());
50         $arr = array('status'=>1,'message'=>'success','data'=>$data);
51  
52         //仅推送给当前连接用户
53         //$server->push($fd, json_encode($arr));
54         
55         //推送给全部连接用户
56         foreach($server->connections as $fd) {
57             $server->push($fd, json_encode($arr));
58         } 
59     }
60  
61     //连接关闭时回调函数
62     public function onClose($server,$fd)
63     {
64         echo "标识{$fd}关闭了连接\n";
65     }
66 }
复制代码

 

前端演示页面:

(省略控制器判断登录状态、分配数据逻辑……)

复制代码
  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4 <meta charset="UTF-8" />
  5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  6 <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  7 <title>Chat</title>
  8 <link rel="stylesheet" type="text/css" href="/static/liaotian/chat.css" />
  9 <script src="/static/liaotian/js/jquery.min.js"></script>
 10 <script src="/static/liaotian/js/flexible.js"></script>
 11 </head>
 12 <body>
 13     <header class="header">
 14         <a class="back" href="javascript:history.back()"></a>
 15         <h5 class="tit">在线聊天</h5>
 16         <a href=""><div class="right">退出</div></a>
 17     </header>
 18  
 19     <!-- 聊天内容 start-->
 20     <div class="message"> </div>
 21     <!-- 聊天内容 end-->
 22  
 23     <!-- 底部 start-->
 24     <div class="footer">
 25         <img id="setbtn" src="/static/liaotian/images/hua.png" alt="" />
 26         <img src="/static/liaotian/images/xiaolian.png" alt="" />
 27         <input type="text" id="msg" value="" maxlength="300">
 28         <p style="background: rgb(17, 79, 142);" id="sendBtn">发送</p>
 29     </div>
 30     <!-- 底部 end-->
 31 </body>
 32 </html>
 33 <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
 34 <script src="https://cdn.bootcss.com/layer/3.1.0/layer.js"></script>
 35 <script type="text/javascript">
 36 $(function () {
 37     var uid = 666;//当前用户id
 38     var token = 'abcdefg';//用户token
 39  
 40     //判断浏览器是否支持WebSocket
 41     var supportsWebSockets = 'WebSocket' in window || 'MozWebSocket' in window;
 42     if (supportsWebSockets) {
 43         //建立WebSocket连接(ip地址换成自己主机ip)
 44         var ws = new WebSocket("ws://127.0.0.1:9501?uid="+uid+"&token="+token);
 45         ws.onopen = function () {
 46             layer.msg('服务器连接成功',{shade:0.1,icon:1,time:600});
 47         };
 48         ws.onerror = function () {
 49             layer.msg('服务器连接失败',{shade:0.1,icon:2,time:600});
 50         };
 51         ws.onmessage = function (evt) {
 52             var data = $.parseJSON(evt.data);
 53             //错误提示
 54             if(data.status != 1){
 55                 layer.alert(data.message,{icon:2});
 56                 return;
 57             }
 58             //消息返回
 59             if (data.status==1 && data.data.message!='') {
 60                 var html = "";
 61                 if (data.data.uid == uid) {
 62                     html += "<div style='word-break:break-all' class=\"show\"><div class=\"time\">"+data.data.post_time+"</div><div class=\"msg\"><img src=\""+data.data.head_img+"\" alt=\"\" /><p><i clas=\"msg_input\"></i>"+data.data.message+"</p></div></div>";
 63                 }else{
 64                     html += "<div style='word-break:break-all' class=\"send\"><div class=\"time\">"+data.data.post_time+"</div><div class=\"msg\"><img src=\""+data.data.head_img+"\" alt=\"\" /><p><i clas=\"msg_input\"></i>"+data.data.message+"</p></div></div>";
 65                 }
 66             }
 67             $(".message").append(html);
 68             setTimeout(function () {
 69                 ($('.message').children("div:last-child")[0]).scrollIntoView();//向上滚动
 70             },100);
 71         };
 72         ws.onclose = function (res) {
 73             
 74         };
 75         //按钮发送
 76         $("#sendBtn").click(function () {
 77             var contents = $("#msg").val().trim();
 78             if(contents == null || contents == ""){
 79                 layer.msg('内容为空',{shade:0.1,icon:2,time:600});            
 80                 return false;
 81             }else{
 82                 ws.send(contents);
 83                 $("#msg").val("");
 84             }
 85         });
 86         //回车发送
 87         $("#msg").keydown(function (evel) {
 88             var that = $(this);
 89             if (evel.keyCode == 13) {
 90                 evel.cancelBubble = true;
 91                 evel.preventDefault();
 92                 evel.stopPropagation();
 93                 var contents = that.val().trim();
 94                 if(contents == null || contents == ""){
 95                     layer.msg('内容为空',{shade:0.1,icon:2,time:600});              
 96                     return false;
 97                 }else{
 98                     ws.send(contents);
 99                     that.val("");
100                 }
101             }
102         });
103     }else{
104         layer.alert("您的浏览器不支持 WebSocket!");
105     }
106 });
107 </script>
108
复制代码

 

服务器移到项目根目录开启服务:

php public/index.php Websocket/start

 

这里的路径,是因为我绑定了home模块为默认模块,tp5默认情况是:php public/index.php index/Websocket/start)

开启成功,查看端口已经被监听:

lsof -i:9501

 

thinkphp 6.0 swoole扩展websocket使用教程-ThinkPHP-PHP中文网

mikel阅读(759)

来源: thinkphp 6.0 swoole扩展websocket使用教程-ThinkPHP-PHP中文网

下面由thinkphp框架教程栏目给大家介绍thinkphp 6.0 swoole扩展websocket使用教程(think-swoole),希望对需要的朋友有所帮助!
thinkphp 6.0 swoole扩展websocket使用教程(think-swoole)

前言
最新版本的TP-SWOOLE变化很大,该文所提供的方法已经无法使用,可以参考 https://github.com/xavieryang007/think-swoole-demo/blob/master/doc/%E6%96%87%E6%A1%A3/4.1-websocket.md

介绍
即将推出的tp6.0,已经适配swoole.并推出think-swoole 3.0,并且默认适配了socketio。和2.0版本在使用方法上面有些许不同。

Websocket 继承与Http,进行websocket连接之前需要一次HTTP请求,如果当期地址支持websocket则返回101,然后进行连接。也就是说并不是我的服务支持websocket后,请求每个连接地址都可以进行websocket连接,而是需要预先适配才可以连接。

参数配置
如果要使用websocket需要在配置中启用,将websocket下的enable设置为true

‘server’           => [

‘host’      => ‘0.0.0.0’, // 监听地址

‘port’      => 808, // 监听端口

‘mode’      => SWOOLE_PROCESS, // 运行模式 默认为SWOOLE_PROCESS

‘sock_type’ => SWOOLE_SOCK_TCP, // sock type 默认为SWOOLE_SOCK_TCP

‘options’   => [

‘pid_file’              => runtime_path() . ‘swoole.pid’,

‘log_file’              => runtime_path() . ‘swoole.log’,

‘daemonize’             => false,

// Normally this value should be 1~4 times larger according to your cpu cores.

‘reactor_num’           => swoole_cpu_num(),

‘worker_num’            => swoole_cpu_num(),

‘task_worker_num’       => 4,//swoole_cpu_num(),

‘enable_static_handler’ => true,

‘document_root’         => root_path(‘public’),

‘package_max_length’    => 20 * 1024 * 1024,

‘buffer_output_size’    => 10 * 1024 * 1024,

‘socket_buffer_size’    => 128 * 1024 * 1024,

‘max_request’           => 3000,

‘send_yield’            => true,

],

],

‘websocket’        => [

‘enabled’       => true,// 开启websocket

‘handler’       => Handler::class,  //自定义wbesocket绑定类

‘parser’        => Parser::class, //自定义解析类

‘route_file’    => base_path() . ‘websocket.php’,

‘ping_interval’ => 25000,

‘ping_timeout’  => 60000,

‘room’          => [

‘type’        => TableRoom::class,

‘room_rows’   => 4096,

‘room_size’   => 2048,

‘client_rows’ => 8192,

‘client_size’ => 2048,

],

],

‘auto_reload’      => true,

‘enable_coroutine’ => true,

‘resetters’        => [],

‘tables’           => [],

handler和parser大大方便了自定义websocket服务,默认系统集成socketio。

本文主要介绍如何使用socketio,这里假设大家有socketio有一定了解和使用基础。

socketIo默认会在请求地址后加相应的参数

同时,socketio默认情况下,会认为 http://url/socket.io/ 是支持websocket服务的地址。

而在tp-swoole3.0内部已经对该地址请求进行了处理

namespace think\swoole\websocket\socketio;

use think\Config;

use think\Cookie;

use think\Request;

class Controller

{

protected $transports = [‘polling’, ‘websocket’];

public function upgrade(Request $request, Config $config, Cookie $cookie)

{

if (!in_array($request->param(‘transport’), $this->transports)) {

return json(

[

‘code’    => 0,

‘message’ => ‘Transport unknown’,

],

400

);

}

if ($request->has(‘sid’)) {

$response = response(‘1:6’);

} else {

$sid     = base64_encode(uniqid());

$payload = json_encode(

[

‘sid’          => $sid,

‘upgrades’     => [‘websocket’],

‘pingInterval’ => $config->get(‘swoole.websocket.ping_interval’),

‘pingTimeout’  => $config->get(‘swoole.websocket.ping_timeout’),

]

);

$cookie->set(‘io’, $sid);

$response = response(’97:0′ . $payload . ‘2:40’);

}

return $response->contentType(‘text/plain’);

}

public function reject(Request $request)

{

return json(

[

‘code’    => 3,

‘message’ => ‘Bad request’,

],

400

);

}

}

TP6.0,插件注册采用了service方式进行了注册,可在tp-swoole 服务注册文件中查看路由注册信息,如果想自定义链接规则,则可以覆盖该路由。

// +———————————————————————-

// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]

// +———————————————————————-

// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.

// +———————————————————————-

// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )

// +———————————————————————-

// | Author: yunwuxin <448901948@qq.com>

// +———————————————————————-

namespace think\swoole;

use Swoole\Http\Server as HttpServer;

use Swoole\Websocket\Server as WebsocketServer;

use think\App;

use think\Route;

use think\swoole\command\Server as ServerCommand;

use think\swoole\facade\Server;

use think\swoole\websocket\socketio\Controller;

use think\swoole\websocket\socketio\Middleware;

class Service extends \think\Service

{

protected $isWebsocket = false;

/**

* @var HttpServer | WebsocketServer

*/

protected static $server;

public function register()

{

$this->isWebsocket = $this->app->config->get(‘swoole.websocket.enabled’, false);

$this->app->bind(Server::class, function () {

if (is_null(static::$server)) {

$this->createSwooleServer();

}

return static::$server;

});

$this->app->bind(‘swoole.server’, Server::class);

$this->app->bind(Swoole::class, function (App $app) {

return new Swoole($app);

});

$this->app->bind(‘swoole’, Swoole::class);

}

public function boot(Route $route)

{

$this->commands(ServerCommand::class);

if ($this->isWebsocket) {

$route->group(function () use ($route) {

$route->get(‘socket.io/’, ‘@upgrade’);

$route->post(‘socket.io/’, ‘@reject’);

})->prefix(Controller::class)->middleware(Middleware::class);

}

}

/**

* Create swoole server.

*/

protected function createSwooleServer()

{

$server     = $this->isWebsocket ? WebsocketServer::class : HttpServer::class;

$config     = $this->app->config;

$host       = $config->get(‘swoole.server.host’);

$port       = $config->get(‘swoole.server.port’);

$socketType = $config->get(‘swoole.server.socket_type’, SWOOLE_SOCK_TCP);

$mode       = $config->get(‘swoole.server.mode’, SWOOLE_PROCESS);

static::$server = new $server($host, $port, $mode, $socketType);

$options = $config->get(‘swoole.server.options’);

static::$server->set($options);

}

}

Socketio默认使用demo

Websocket路由配置方法
在app目录下新建websocket.php文件,其中需要注意,由于使用了反射,闭包参数名称不能随意定义,不然无法注入。第一个参数是websocket,是当前websocket的Server对象,第二个参数data是客户端发送的数据。其中socketio emit的第一个参数和Websocket::on的第一个参数一致,作为事件名称。

/**

* Author:Xavier Yang

* Date:2019/6/5

* Email:499873958@qq.com

*/

use \think\swoole\facade\Websocket;

Websocket::on(“test”, function (\think\swoole\Websocket $websocket, $data) {

//var_dump($class);

$websocket->emit(“test”, “asd”);

});

Websocket::on(“test1”, function ($websocket, $data) {

$websocket->emit(“test”, “asd”);

});

Websocket::on(“join”, function (\think\swoole\Websocket $websocket, $data) {

$websocket->join(“1”);

});

参考如上方法即可使用全新的websocket服务。当然tp-swoole3.0同样还有许多其他的新功能,这些功能需要大家去摸索尝试。
我也会在接下来的文章中,一起与大家分享我的使用过程。

以上就是thinkphp 6.0 swoole扩展websocket的使用的详细内容,更多请关注php中文网其它相关文章!

ThinkPHP5.1 安装 workerman 指导 - 云+社区 - 腾讯云

mikel阅读(759)

来源: ThinkPHP5.1 安装 workerman 指导 – 云+社区 – 腾讯云

★ 背景

  • 最近需要在自己的网站后台,设计消息推送业务,通过网上资料参考,觉得 workerman 是个很好的选择,在此记录一下ThinkPHP5.1 框架下的安装操作,希望可以帮到更多的人 …

workerman 手册

  • 环境
框架版本:ThinkPHP5.1.2
使用工具:composer
系统环境:Win10、CentOS7.2

☆ 指导步骤

首先,因为配置条件多有不同,需要根据自己的情况稍作调整的哦 (仅作为友情提示…)

①. 进入项目根目录,运行 composer 命令

  • 安装命令如下:
composer require topthink/think-worker
  • 此时,会有提示信息:
Using version ^3.0 for topthink/think-worker
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - topthink/think-worker v3.0.3 requires topthink/framework ^6.0.0 -> satisfiable by topthink/framework[6.0.x-dev, v6.0.0-rc2, v6.0.0-rc3, v6.0.0-rc4] but these conflict with your requirements or minimum-stability.
    - topthink/think-worker v3.0.2 requires topthink/framework ^6.0.0 -> satisfiable by topthink/framework[6.0.x-dev, v6.0.0-rc2, v6.0.0-rc3, v6.0.0-rc4] but these conflict with your requirements or minimum-stability.
    - topthink/think-worker v3.0.1 requires topthink/framework ^6.0.0 -> satisfiable by topthink/framework[6.0.x-dev, v6.0.0-rc2, v6.0.0-rc3, v6.0.0-rc4] but these conflict with your requirements or minimum-stability.
    - topthink/think-worker v3.0.0 requires topthink/framework ^6.0.0 -> satisfiable by topthink/framework[6.0.x-dev, v6.0.0-rc2, v6.0.0-rc3, v6.0.0-rc4] but these conflict with your requirements or minimum-stability.
    - Installation request for topthink/think-worker ^3.0 -> satisfiable by topthink/think-worker[v3.0.0, v3.0.1, v3.0.2, v3.0.3].


Installation failed, reverting ./composer.json to its original content.
  • 解释: 这是因为,在不填写所需扩展的版本号前提下,会默认下载最新版本 但是,当前的框架版本很可能不支持,比如,此时要求必须要是 ThinkPHP6.0 框架 而鄙人的版本是 ThinkPHP5.1.2
  • 解决方案:就是,直接指定所需要的扩展包版本

当然,如果你的 ThinkPHP 版本足够高,此时应该会直接顺利的安装,后面的就无需多看咯

②. 获取可选择的 workerman 版本

为了指定安装的版本,所以我们要知道,有哪些可选择的版本

  • composer.json 文件中的 "require" 数组中,先补充一条数据:"topthink/think-worker":"0.1"
  • 此时,命令行执行:composer update
  • 根据自己的 ThinkPHP 版本选择合适的扩展
> 以我为例,试着选择了 "v3.0.0" (依然版本要求太高)、 "v2.0.9" (当前较合适)
> 然后进行安装操作
> 此时可以有两种方式,个人建议选用后者
> 
> 第一种方式:
> 直接修改前面所提及的 "composer.json" 文件中的版本号:"topthink/think-worker":"v2.0.9"> 然后,再次执行一遍命令:composer update
> 
> 第二种方式:
> 删掉前面 "composer.json" 文件中 补充测试的内容:"topthink/think-worker":"0.1"
> 然后,执行命令:composer require topthink/think-worker=v2.0.9
  • 执行的打印信息,如下:
  • 【安装完成】 安装成功后,你可以发现会多出 "/vendor/topthink/think-worker""/vendor/workerman" 目录 并且,在目录 "/config" 中,会自动生成 workerman 对应的三个配置文件

附录

参考文章

  • Linux 系统检测 Linux系统可以使用以下脚本测试本机 PHP 环境是否满足 WorkerMan 运行要求
curl -Ss http://www.workerman.net/check.php | php

上面脚本如果全部显示ok,则代表满足 WorkerMan 要求

composer安装tp6引入各种包问题解决笔记! - 简书

mikel阅读(1337)

来源: composer安装tp6引入各种包问题解决笔记! – 简书

执行composer require topthink/framework,报错,原因proc_open函数被禁用

  [Symfony\Component\Process\Exception\RuntimeException]                                   
  The Process class relies on proc_open, which is not available on your PHP installation.   
解决方法:

打开php.ini,搜索disable_functions,找到proc_open并删除即可。

image.png

 

执行composer require topthink/think-image报错原因:
pcntl_signal函数被禁用,同上删除该禁用,重启PHP

  [ErrorException]                                       
  pcntl_signal() has been disabled for security reasons   
执行composer require topthink/think-worker 报错:
解决方法:安装fileinfo扩展


./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - topthink/think-worker v3.0.4 requires ext-fileinfo * -> the requested PHP extension fileinfo is missing from your system.
    - topthink/think-worker v3.0.3 requires ext-fileinfo * -> the requested PHP extension fileinfo is missing from your system.
    - topthink/think-worker v3.0.2 requires ext-fileinfo * -> the requested PHP extension fileinfo is missing from your system.
    - topthink/think-worker v3.0.1 requires ext-fileinfo * -> the requested PHP extension fileinfo is missing from your system.
    - topthink/think-worker v3.0.0 requires ext-fileinfo * -> the requested PHP extension fileinfo is missing from your system.
    - Installation request for topthink/think-worker ^3.0 -> satisfiable by topthink/think-worker[v3.0.0, v3.0.1, v3.0.2, v3.0.3, v3.0.4].

  To enable extensions, verify that they are enabled in your .ini files:
    - /www/server/php/73/etc/php.ini
  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.

Installation failed, reverting ./composer.json to its original content.


image.png

作者:DragonersLi
链接:https://www.jianshu.com/p/17fa22374667
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

thinkphp5下使用WebSocket_gzmyh的博客-CSDN博客_thinkphp websocket

mikel阅读(915)

来源: thinkphp5下使用WebSocket_gzmyh的博客-CSDN博客_thinkphp websocket

最近有个项目需求是这样的:软件端会向服务器发送请求,获取一些信息。然后对获取过来的信息进行处理,再返回信息的id

方式一:软件端那边调用接口,一分钟请求一次。

问题出现:如果有几万个人同时用软件,就会产生大量的http请求,导致负载过高。因此需求考虑到第二种方式。

方式二:使用WebSocket,进行一次长连接,这样就减少了大量的请求。

因为对于webscoket要求不高,因此就选择了Workerman,这也是thinkphp5封装好的扩展,直接下载下来用。

参考手册:thinkphp5.1和workerman开发手册

下面开始:

使用composer下载:

composer require topthink/think-worker
下载下来后会有一些文件,重点看config里面的worker.php和worker_server.php。这两个是不同的监听配置,我使用的是worker_server.php

它的默认配置是这样的

return [
// 扩展自身需要的配置
‘protocol’ => ‘websocket’, // 协议 支持 tcp udp unix http websocket text
‘host’ => ‘0.0.0.0’, // 监听地址
‘port’ => 2346, // 监听端口
‘socket’ => ‘hd.com:2346’, // 完整监听地址
‘context’ => [], // socket 上下文选项
‘worker_class’ => ”, // 自定义Workerman服务类名 支持数组定义多个服务

// 支持workerman的所有配置参数
‘name’ => ‘thinkphp’,
‘count’ => 4,
‘daemonize’ => false,
‘pidFile’ => Env::get(‘runtime_path’) . ‘worker.pid’,

// 支持事件回调
// onWorkerStart
‘onWorkerStart’ => function ($worker) {

},
// onWorkerReload
‘onWorkerReload’ => function ($worker) {

},
// onConnect
‘onConnect’ => function ($connection) {

},
// onMessage
‘onMessage’ => function ($connection, $data) {
$connection->send(‘你成功了’);
},
// onClose
‘onClose’ => function ($connection) {

},
// onError
‘onError’ => function ($connection, $code, $msg) {
echo “error [ $code ] $msg\n”;
},
];
这时你打开命令行(cmd),切换到你项目根目录下

E:\wamp64\www\hd\v2018>E:\wamp64\bin\php\php7.0.4\php.exe think worker:server

因为我没有配置php的环境变量,所有就时候这种方式了。这时会看到这样的结果说明服务启动成功

 

打开chrome浏览器,按F12打开调试控制台,在Console一栏输入(或者把下面代码放入到html页面用js运行)

// 假设服务端ip为127.0.0.1
ws = new WebSocket(“ws://127.0.0.1:2000”);
ws.onopen = function() {
alert(“连接成功”);
};
ws.onmessage = function(e) {
alert(“收到服务端的消息:” + e.data);
};
这是你会收到“你成功了”的字样。

接下来就是真正的开发流程了。

一般情况下我们会创建一个服务类(必须要继承 think\worker\Server),然后设置属性和添加回调方法,这是我写的一个类

<?php
// +———————————————————————-
// | websocket
// +———————————————————————-
// | Author: myh
// +———————————————————————-

namespace app\worker;

use think\worker\Server;
use app\common\api\BaseApi;

class Worker extends Server
{
protected $socket = ‘http://0.0.0.0:2346’;

public function onMessage($connection,$data)
{
$data = explode(‘|’, $data);
switch ($data[0]) {
case ‘software_send_msg’:
if(!isset($data[1]) || empty($data[1])) {
$list = json_encode([‘result’=>’error’,’message’=>’参数为空’]);
}else{
$account = $data[1];
$uid = BaseApi::findData(8,2,[[‘user_login’,’=’,$account]],’id’);

if($uid){
list($data) = BaseApi::getListOne(16,[[‘user_id’,’=’,$uid],[‘status’,’=’,0]]);//16-software_send_msg
if($data){
$list = [];
foreach ($data as $k => $v) {
$list[$k][‘id’] = $v[‘id’];
$list[$k][‘type’] = $v[‘type’];
$list[$k][‘msg’] = $v[‘msg’];
}

$list = json_encode([‘result’=>’success’,’data’=>json_encode($list)]);
}else{
$list = json_encode([‘result’=>’error’, ‘message’=>’数据为空’]);
}

}else{
$list = json_encode([‘result’=>’error’, ‘message’=>’找不到该账号信息’]);
}
}

break;

case ‘software_send_msg2’:
$msg = 3333;
break;

default:
$list = json_encode([‘result’=>’error’]);
break;
}

$connection->send($list);//这里把数据发送给客户端

}

}
这时要对worker_server.php进行修改,删掉之前的配置,只要加上这个即可

return [
‘worker_class’ => ‘app\worker\Worker’,
];
控制器:

public function ws()
{
return $this->fetch(‘:ws’);
}
模板:

<!DOCTYPE html>
<html xmlns:v-on=”http://www.w3.org/1999/xhtml”>
<head>
<meta charset=”utf-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no”>
<title>ThinkCMF WebSocket Demo</title>

<script src=”__STATIC__/js/JQuery-2.0.3.min.js”></script>
</head>
<body>

<div id=”app”>
软件模拟获取最新消息:
<button class=”get-msg”>请求</button>

<div class=”return-msg”>

</div>
</div>

<script>

$(document).on(‘click’,’.get-msg’,function(){
ws = new WebSocket(“ws://127.0.0.1:2346”);

//组织参数
var param = new Array();
param.push(‘software_send_msg’);
param.push(‘wydyhdzh’);

ws.onopen = function() {
ws.send(param.join(‘|’));//向服务器返送信息
};

ws.onmessage = function(e) {//服务器返回信息
var data = JSON.parse(e.data);

if(data.result == ‘success’){
var list = JSON.parse(data.data);
$(‘.return-msg’).html(data.data);
}
};
})

</script>
</body>
</html>

 

整个流程就是这样,不明白可以留言
————————————————
版权声明:本文为CSDN博主「gzmyh」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/gzmyh/article/details/89874357

ThinkPHP6 Workerman 基本使用-ThinkPHP-PHP中文网

mikel阅读(835)

来源: ThinkPHP6 Workerman 基本使用-ThinkPHP-PHP中文网

Workerman
Workerman是一款纯PHP开发的开源高性能的PHP socket 服务器框架。被广泛的用于手机app、手游服务端、网络游戏服务器、聊天室服务器、硬件通讯服务器、智能家居、车联网、物联网等领域的开发。 支持TCP长连接,支持Websocket、HTTP等协议,支持自定义协议。基于workerman开发者可以更专注于业务逻辑开发,不必再为PHP Socket底层开发而烦恼。

安装

首先通过 composer 安装

composer require topthink/think-worker

使用

使用Workerman作为HttpServer

在命令行启动服务端

php think worker

然后就可以通过浏览器直接访问当前应用

http://localhost:2346

linux下面可以支持下面指令

php think worker [start|stop|reload|restart|status]

workerman的参数可以在应用配置目录下的worker.php里面配置。

由于onWorkerStart运行的时候没有HTTP_HOST,因此最好在应用配置文件中设置app_host

SocketServer

在命令行启动服务端(需要2.0.5+版本)

php think worker:server

默认会在0.0.0.0:2345开启一个websocket服务。

如果需要自定义参数,可以在config/worker_server.php中进行配置,包括:

配置参数 描述
protocol 协议
host 监听地址
port 监听端口
socket 完整的socket地址
并且支持workerman所有的参数(包括全局静态参数)。

也支持使用闭包方式定义相关事件回调。

return [

‘socket’    =>  ‘http://127.0.0.1:8000’,

‘name’      =>  ‘thinkphp’,

‘count’     =>  4,

‘onMessage’ =>  function($connection, $data) {

$connection->send(json_encode($data));

},

];

也支持使用自定义类作为Worker服务入口文件类。例如,我们可以创建一个服务类(必须要继承 think\worker\Server),然后设置属性和添加回调方法

namespace app\http;

use think\worker\Server;

class Worker extends Server

{

protected $socket = ‘http://0.0.0.0:2346’;

public function onMessage($connection,$data)

{

$connection->send(json_encode($data));

}

}

支持workerman所有的回调方法定义(回调方法必须是public类型)

然后在worker_server.php中增加配置参数:

return [

‘worker_class’  =>  ‘app\http\Worker’,

];

定义该参数后,其它配置参数均不再有效。

在命令行启动服务端

php think worker:server

然后在浏览器里面访问

http://localhost:2346

如果在Linux下面,同样支持reload|restart|stop|status 操作

php think worker:server reload

推荐教程:《ThinkPHP》《PHP教程》《Workerman教程》

以上就是ThinkPHP6 Workerman 基本使用的详细内容,更多请关注php中文网其它相关文章!

Workerman wss 宝塔 Apache2.4 配置 - 技术小站

mikel阅读(759)

来源: Workerman wss 宝塔 Apache2.4 配置 – 技术小站

我测试的是 https://www.workerman.net/workerman-chat 项目。

Workerman 文档:http://doc.workerman.net/315297

    # Proxy Config
    SSLProxyEngine on

    ProxyRequests Off
    ProxyPass /wss ws://127.0.0.1:7272/wss
    ProxyPassReverse /wss ws://127.0.0.1:7272/wss
// 证书是会检查域名的,请使用域名连接
ws = new WebSocket("wss://guodapeng.icu/wss");

ws.onopen = function() {
    alert("连接成功");
    ws.send('tom');
    alert("给服务端发送一个字符串:tom");
};
ws.onmessage = function(e) {
    alert("收到服务端的消息:" + e.data);
};

浏览器跑一下这个js,连接成功了。

宝塔定时任务执行php源码任务_PHP:与workerman结合实现定时任务_悠悠黄鹤楼的博客-CSDN博客

mikel阅读(900)

来源: 宝塔定时任务执行php源码任务_PHP:与workerman结合实现定时任务_悠悠黄鹤楼的博客-CSDN博客

workerman是一个高性能的PHP socket 服务器框架,workerman基于PHP多进程以及libevent事件轮询库,PHP开发者只要实现一两个接口,便可以开发出自己的网络应用,例如Rpc服务、聊天室服务器、手机游戏服务器等。

workerman的目标是让PHP开发者更容易的开发出基于socket的高性能的应用服务,而不用去了解PHP socket以及PHP多进程细节。 workerman本身是一个PHP多进程服务器框架,具有PHP进程管理以及socket通信的模块,所以不依赖php-fpm、nginx或者apache等这些容器便可以独立运行

以下我们来重点来来workerman是如何实现定时任务的

一、下载workerman

https://www.workerman.net/download

二、下载workerman/mySQL

http://doc3.workerman.net/640201

1、定时函数为匿名函数(闭包)

use WorkermanWorker;use WorkermanLibTimer;require_once ‘./Workerman/Autoloader.php’;$task = new Worker();// 开启多少个进程运行定时任务,注意多进程并发问题$task->count = 1;$task->onWorkerStart = function($task){ // 每2.5秒执行一次 $time_interval = 2.5; Timer::add($time_interval, function() { echo “task run”; });};// 运行workerWorker::runAll();
2、定时函数为普通函数

require_once ‘./Workerman/Autoloader.php’;use WorkermanWorker;use WorkermanLibTimer;// 普通的函数function send_mail($to, $content){ echo “send mail …”;}$task = new Worker();$task->onWorkerStart = function($task){ $to = ‘workerman@workerman.net’; $content = ‘hello workerman’; // 10秒后执行发送邮件任务,最后一个参数传递false,表示只运行一次 Timer::add(10, ‘send_mail’, array($to, $content), false);};// 运行workerWorker::runAll();
3、定时函数为类的方法

require_once ‘./Workerman/Autoloader.php’;use WorkermanWorker;use WorkermanLibTimer;class Mail{ // 注意,回调函数属性必须是public public function send($to, $content) { echo “send mail …”; }}$task = new Worker();$task->onWorkerStart = function($task){ // 10秒后发送一次邮件 $mail = new Mail(); $to = ‘workerman@workerman.net’; $content = ‘hello workerman’; Timer::add(10, array($mail, ‘send’), array($to, $content), false);};// 运行workerWorker::runAll();
4、定时函数为类方法(类内部使用定时器)

require_once ‘./Workerman/Autoloader.php’;use WorkermanWorker;use WorkermanLibTimer;class Mail{ // 注意,回调函数属性必须是public public function send($to, $content) { echo “send mail …”; } public function sendLater($to, $content) { // 回调的方法属于当前的类,则回调数组第一个元素为$this Timer::add(10, array($this, ‘send’), array($to, $content), false); }}$task = new Worker();$task->onWorkerStart = function($task){ // 10秒后发送一次邮件 $mail = new Mail(); $to = ‘workerman@workerman.net’; $content = ‘hello workerman’; $mail->sendLater($to, $content);};// 运行workerWorker::runAll();
5、定时函数为类的静态方法

require_once ‘./Workerman/Autoloader.php’;use WorkermanWorker;use WorkermanLibTimer;class Mail{ // 注意这个是静态方法,回调函数属性也必须是public public static function send($to, $content) { echo “send mail …”; }}$task = new Worker();$task->onWorkerStart = function($task){ // 10秒后发送一次邮件 $to = ‘workerman@workerman.net’; $content = ‘hello workerman’; // 定时调用类的静态方法 Timer::add(10, array(‘Mail’, ‘send’), array($to, $content), false);};// 运行workerWorker::runAll();
6、定时函数为类的静态方法(带命名空间)

namespace Task;require_once ‘./Workerman/Autoloader.php’;use WorkermanWorker;use WorkermanLibTimer;class Mail{ // 注意这个是静态方法,回调函数属性也必须是public public static function send($to, $content) { echo “send mail …”; }}$task = new Worker();$task->onWorkerStart = function($task){ // 10秒后发送一次邮件 $to = ‘workerman@workerman.net’; $content = ‘hello workerman’; // 定时调用带命名空间的类的静态方法 Timer::add(10, array(‘TaskMail’, ‘send’), array($to, $content), false);};// 运行workerWorker::runAll();
7、定时器中销毁当前定时器(use闭包方式传递$timer_id)

use WorkermanWorker;use WorkermanLibTimer;require_once ‘./Workerman/Autoloader.php’;$task = new Worker();$task->onWorkerStart = function($task){ // 计数 $count = 1; // 要想$timer_id能正确传递到回调函数内部,$timer_id前面必须加地址符 & $timer_id = Timer::add(1, function()use(&$timer_id, &$count) { echo “Timer run $count”; // 运行10次后销毁当前定时器 if($count++ >= 10) { echo “Timer::del($timer_id)”; Timer::del($timer_id); } });};// 运行workerWorker::runAll();
8、定时器中销毁当前定时器(参数方式传递$timer_id)

require_once ‘./Workerman/Autoloader.php’;use WorkermanWorker;use WorkermanLibTimer;class Mail{ public function send($to, $content, $timer_id) { // 临时给当前对象添加一个count属性,记录定时器运行次数 $this->count = empty($this->count) ? 1 : $this->count; // 运行10次后销毁当前定时器 echo “send mail {$this->count}…”; if($this->count++ >= 10) { echo “Timer::del($timer_id)”; Timer::del($timer_id); } }}$task = new Worker();$task->onWorkerStart = function($task){ $mail = new Mail(); // 要想$timer_id能正确传递到回调函数内部,$timer_id前面必须加地址符 & $timer_id = Timer::add(1, array($mail, ‘send’), array(‘to’, ‘content’, &$timer_id));};// 运行workerWorker::runAll();
9、只在指定进程中设置定时器

一个worker实例有4个进程,只在id编号为0的进程上设置定时器。

use WorkermanWorker;use WorkermanLibTimer;require_once ‘./Workerman/Autoloader.php’;$worker = new Worker();$worker->count = 4;$worker->onWorkerStart = function($worker){ // 只在id编号为0的进程上设置定时器,其它1、2、3号进程不设置定时器 if($worker->id === 0) { Timer::add(1, function(){ echo “4个worker进程,只在0号进程设置定时器”; }); }};// 运行workerWorker::runAll();
看看完整的示例

shipments.php用来写定时任务

<?php /** * Created by PhpStorm. * User: Administrator * Date: 2018/11/29 * Time: 16:59 */use WorkermanWorker;use WorkermanLibTimer;require_once “Workerman/Autoloader.php”;require_once “Connection.php”;$task = new Worker();$task->onWorkerStart = function ($task) { global $db, $redis; $db = new WorkermanMySQLConnection(‘127.0.0.1’, ‘3306’, ‘root’, ‘root’, ‘test’); $redis = new Redis(); $redis->connect(‘127.0.0.1’, 6379); $redis->auth(“qqq123123.”); $time_interval = 0.1; Timer::add($time_interval, function () { global $db, $redis; $insert[‘name’] = 123; $db->insert(‘shipments’)->cols($insert)->query();// sleep(100); });};function curlGet($url = ”, $options = []){ $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 30); if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch); curl_close($ch); return $data;}function newGetOrderInfo($taobao, $orderId){ $taobao = urlencode($taobao); $url = “http://114.55.144.79/taobao/TradeFullinfoGetRequest.php?shop=$taobao&tid=$orderId”; $json = curlGet($url); return json_decode($json, true)[‘trade’];}Worker::runAll();

点击了解更多去学习:非常使用的代码优化,怎么才能写好代码

相关资源:phpworkerman定时任务的实现代码-其它代码类资源
————————————————
版权声明:本文为CSDN博主「悠悠黄鹤楼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42346935/article/details/112150750

宝塔 Linux centos Workerman换域名步骤_php菜鸟技术天地-CSDN博客

mikel阅读(594)

来源: 宝塔 Linux centos Workerman换域名步骤_php菜鸟技术天地-CSDN博客

就是以前用www.xxx.com域名,Workerman已经正常了,现在更新域名换成cms.xxx.com

1.绑定域名到服务器

2.创建SSL证书

3.在服务器创建虚拟主机

 

4.把SSL证书上传到路径/www/server/panel/vhost/ssl/www.xxx.com/

 

5.修改代码中证书路径:\vendor\topthink\think-worker\src\Server.php

 

6.启动Workerman测试

先进入项目根目录/www/wwwroot/card.xxx.com

命令启动

php server.php start

7.测试正确,把这个加入服务器开启任务中

https://blog.csdn.net/haibo0668/article/details/106734528
————————————————
版权声明:本文为CSDN博主「我是高手高手高高手」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/haibo0668/article/details/107186152