THINKPHP5整合workerman+gateway

这次要开发聊天系统 , 需要用到WebSocket   我使用的是workerman+gateway,为了方便后面再用,做个简单记录

首先要特别注意的是,端口要开放,如果端口未开放,会出现连接时握手失败的情况,这里我用的商品是  801   和  802

1、安装workerman和gateway

composer require topthink/think-worker
composer require workerman/gatewayclient

2、添加server.php文件,后成需要在CLI模式下运行

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

#!/usr/bin/env php

<?php

ini_set('display_errors''on');

if(strpos(strtolower(PHP_OS), 'win') === 0)

{

    exit("start.php not support windows.\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('APP_PATH', __DIR__ . '/application/');

define('BIND_MODULE','push/Run');

// 加载框架引导文件

require __DIR__ . '/thinkphp/start.php';

3、创建push模块新建两个控制器Run.php    Events.php

Start.php

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

<?php

namespace app\push\controller;

use Workerman\Worker;

use GatewayWorker\Register;

use GatewayWorker\BusinessWorker;

use GatewayWorker\Gateway;

class Run extends Worker{

  /**

     * 构造函数

     * @access public

     */

    public function __construct(){

        //由于是手动添加,因此需要注册命名空间,方便自动加载,具体代码路径以实际情况为准

                \think\Loader::addNamespace([

                    'Workerman' => VENDOR_PATH . 'Workerman/workerman',

                    'GatewayWorker' =>VENDOR_PATH . 'Workerman/gateway-worker/src',

                ]);

                //初始化各个GatewayWorker

        //初始化register

        new Register('text://0.0.0.0:801');

          

         //初始化 bussinessWorker 进程

        $worker new BusinessWorker();

        $worker->name = 'WebIMBusinessWorker';

        $worker->count = 4;

        $worker->registerAddress = '127.0.0.1:801';

        //设置处理业务的类,此处制定Events的命名空间

        $worker->eventHandler = '\app\push\controller\Events';

        // 初始化 gateway 进程

        $gateway new Gateway("websocket://0.0.0.0:802");

        $gateway->name = 'WebIMGateway';

        $gateway->count = 4;

        $gateway->lanIp = '127.0.0.1';

        $gateway->startPort = 2900;

        $gateway->registerAddress = '127.0.0.1:801';

          

         //运行所有Worker;

        Worker::runAll();

    }

}

Events.php

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

<?php

namespace app\push\controller;

use GatewayWorker\Lib\Gateway;

/**

 * 主逻辑

 * 主要是处理 onConnect onMessage onClose 三个方法

 * onConnect 和 onClose 如果不需要可以不用实现并删除

 */

class Events{

/**

    * 当客户端发来消息时触发

    * @param int $client_id 连接id

    * @param mixed $data 具体消息

    */

    public static function onMessage($client_id$data){

       $message = json_decode($data, true);

       $message_type $message['type'];

       switch($message_type) {

           case 'init':

               // uid

               $uid $message['id'];

               // 设置session

               $_SESSION = [

                   'username' => $message['username'],

                   'avatar'   => isset($message['avatar'])?$message['avatar']:'',

                   'id'       => $uid,

                   'sign'     => $message['sign'],

                    'type'=> $type,

               ];

               // 将当前链接与uid绑定

               Gateway::bindUid($client_id$uid);

               // 通知当前客户端初始化

               $init_message array(

                   'message_type' => 'init',

                   'id'           => $uid,

               );

               Gateway::sendToClient($client_id, json_encode($init_message));

               return;

               break;

           case 'chatMessage':

               // 聊天消息

               $type $message['data']['to']['type'];

               $to_id $message['data']['to']['id'];

               $uid $_SESSION['id'];

  

               $chat_message = [

                    'message_type' => 'chatMessage',

                    'data' => [

                        'username' => $_SESSION['username'],

                        'avatar'   => $_SESSION['avatar'],

                        'id'       => $type === 'friend' $uid $to_id,

                        'type'     => $type,

                        'content'  => htmlspecialchars($message['data']['mine']['content']),

                        'timestamp'=> time()*1000,

                    ]

               ];

          

               return Gateway::sendToUid($to_id, json_encode($chat_message));

               break;

           case 'hide':

           case 'online':

               $status_message = [

                   'message_type' => $message_type,

                   'id'           => $_SESSION['id'],

               ];

               $_SESSION['online'] = $message_type;

               Gateway::sendToAll(json_encode($status_message));

               return;

               break;

           case 'ping':

               return;

           default:

               echo "unknown message $data" . PHP_EOL;

       }

    }

    /**

     * 当客户端连接时触发

     * 如果业务不需此回调可以删除onConnect

     *

     * @param int $client_id 连接id

     */

    public static function onConnect($client_id)

    {

         

        var_dump($client_id);

        Gateway::sendToClient($client_id,json_encode(['status'=>"success",'msg'=>"连接成功"]));

        Gateway::sendToAll("连接成功");

    }

    /**

     * 当连接断开时触发的回调函数

     * @param $connection

     */

    public static function onClose($client_id){

       $logout_message = [

           'message_type' => 'logout',

           'id'           => $_SESSION['id']

       ];

       Gateway::sendToAll(json_encode($logout_message));

    }

    /**

     * 当客户端的连接上发生错误时触发

     * @param $connection

     * @param $code

     * @param $msg

     */

    public static function onError($client_id$code$msg)

    {

        echo "error $code $msg\n";

    }

    /**

     * 每个进程启动

     * @param $worker

     */

    public static function onWorkerStart($worker)

    {

    }

}

然后执行命令开启进程

php server.php start


前端示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

<!DOCTYPE html>

<html>

<head>

    <meta charset="UTF-8">

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <title>Title</title>

    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>

</head>

<body>

  

<script>

    ws = new WebSocket("ws:0.0.0.0:802");    //填你线上服务端地址

    // 服务端主动推送消息时会触发这里的onmessage

    ws.onopen = function(){

        console.info("与服务端连接成功");

        ws.send('test msg\n');//相当于发送一个初始化信息

        console.info("向服务端发送心跳包字符串");

    };

  

    ws.onmessage = function(e){

        // json数据转换成js对象

        var data = eval("("+e.data+")");

        console.log(data.msg);

    };

  

    ws.onclose = function(e){

        console.log(e);

    };

  

</script>

  

</body>

</html>

 文章转载自:THINKPHP5整合workerman+gateway - 智昕 - 博客园

做个保留,便于后续使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThinkPHP 5.1 可以使用 Workerman 实现实时推送功能,具体实现步骤如下: 1. 安装 Workerman 可以使用 Composer 安装 Workerman: ``` composer require workerman/workerman ``` 2. 创建 Workerman 控制器 在应用的 controller 目录下创建 Workerman 控制器,例如创建 `Push.php`,并在该控制器中实现推送功能: ```php namespace app\controller; use think\worker\Server; class Push extends Server { // 监听的地址和端口号 protected $socket = 'websocket://0.0.0.0:2346'; // 接收到客户端消息时触发 public function onMessage($connection, $data) { // 将客户端发送的消息广播给所有客户端 foreach ($this->worker->connections as $conn) { $conn->send($data); } } } ``` 3. 在路由中定义 Workerman 路由 在 `route` 目录下的 `route.php` 文件中定义 Workerman 路由,例如: ```php use think\facade\Route; // 定义 Workerman 路由 Route::get('push', 'push/index'); ``` 4. 启动 Workerman 服务 在命令行中使用以下命令启动 Workerman 服务: ``` php think worker:server ``` 5. 在页面中调用推送接口 在需要推送消息的页面中,调用推送接口,例如: ```javascript var ws = new WebSocket('ws://localhost:2346'); ws.onopen = function() { ws.send('Hello, Workerman!'); }; ws.onmessage = function(event) { console.log(event.data); }; ``` 以上就是使用 ThinkPHP 5.1 实现 Workerman 的推送功能的步骤。需要注意的是,在使用 Workerman 时需要开启 PHP 的长连接,因此需要使用 CLI 环境运行 PHP。此外,需要在浏览器中测试推送功能时,需要使用支持 WebSocket 的浏览器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值