tp5.0整合phpsocketio推送消息完整代码,自己写的,已经亲测过了,不会有任何问题

qdmdxgg

在网上百度了好多关于这一块的,都没有找到完整的教程,这个是我自己写,完完全全可以实现,分享出来给需要的人

PHPSocket.IO手册链接:https://www.workerman.net/phpsocket_io

1.安装

cd到项目的根目录,执行安装
composer require workerman/phpsocket.io

2.入口文件
也是在项目根目录,创建server.php文件,写入下面代码
<?php
define('APP_PATH', __DIR__ . '/application/');
define('BIND_MODULE','socketio/Server/index');
// 加载框架引导文件
require __DIR__ . '/thinkphp/start.php';

3.创建控制器文件,也是第2个步骤的socketio/Server/index
├─application 应用目录
│ ├─socketio 新创建目录
│ │ ├─controller
│ │ │ ├─Server.php 启动文件

4.在Server.php文件写入下面代码
<?php
namespace app\socketio\controller;

require_once VENDOR_PATH . "workerman/phpsocket.io/src/autoload.php";

use Workerman\Worker;
use Workerman\Timer;
use PHPSocketIO\SocketIO;
use Workerman\Protocols\Http\Request;
use Workerman\Connection\TcpConnection;

class Server
{

    public function index()
    {
        // 全局数组保存uid在线数据
        $uidConnectionMap = array();
        // 记录最后一次广播的在线用户数
        $last_online_count = 0;
        // 记录最后一次广播的在线页面数
        $last_online_page_count = 0;

        $io = new SocketIO(2120);//socket的端口

        // 客户端发起连接事件时,设置连接socket的各种事件回调
        $io->on('connection', function($socket){
            // 当客户端发来登录事件时触发
            $socket->on('login', function ($uid)use($socket){
                global $uidConnectionMap, $last_online_count, $last_online_page_count;
                // 已经登录过了
                if(isset($socket->uid)){
                    return;
                }
                // 更新对应uid的在线数据
                $uid = (string)$uid;
                if(!isset($uidConnectionMap[$uid]))
                {
                    $uidConnectionMap[$uid] = 0;
                }
                // 这个uid有++$uidConnectionMap[$uid]个socket连接
                ++$uidConnectionMap[$uid];
                // 将这个连接加入到uid分组,方便针对uid推送数据
                $socket->join($uid);
                $socket->uid = $uid;
                // 更新这个socket对应页面的在线数据
                //$socket->emit('update_online_count', "当前<b>{$last_online_count}</b>人在线,共打开<b>{$last_online_page_count}</b>个页面");
            });

            // 当客户端断开连接是触发(一般是关闭网页或者跳转刷新导致)
            $socket->on('disconnect', function () use($socket) {
                if(!isset($socket->uid))
                {
                     return;
                }
                global $uidConnectionMap, $io;
                // 将uid的在线socket数减一
                if(--$uidConnectionMap[$socket->uid] <= 0)
                {
                    unset($uidConnectionMap[$socket->uid]);
                }
            });
        });

        // 当$sender_io启动后监听一个http端口,通过这个端口可以给任意uid或者所有uid推送数据
        $io->on('workerStart', function () use ($io) {
            $inner_http_worker = new Worker('http://0.0.0.0:7064');//这里IP不用改变,用的内网通讯,端口不能与socket端口想通
            $inner_http_worker->onMessage = function (TcpConnection $http_connection, Request $request) use ($io) {
                global $uidConnectionMap;
                $post = $request->post();
                $post = $post ? $post : $request->get();
                // 推送数据的url格式 type=publish&to=uid&content=xxxx
                switch(@$post['type']){
                    case 'publish':
                        $to = @$post['to'];
                        $post['content'] = htmlspecialchars(@$post['content']);
                        // 有指定uid则向uid所在socket组发送数据
                        if($to){
                            $io->to($to)->emit('new_msg', $post['content']);
                        // 否则向所有uid推送数据
                        }else{
                            $io->emit('new_msg', @$post['content']);
                        }
                        // http接口返回,如果用户离线socket返回fail
                        if($to && !isset($uidConnectionMap[$to])){
                            return $http_connection->send('offline');
                        }else{
                            return $http_connection->send('ok');
                        }
                }
                return $http_connection->send('fail');
            };
            $inner_http_worker->listen();
        });

        Worker::runAll();
    }
}

5.客户端链接:
<script src='http://cdn.bootcss.com/socket.io/1.3.7/socket.io.js'></script>

var socket = io('http://laodiyuncha.com:2120');
var uid = 'user_1';//这个uid根据自己的项目自定义
socket.on('connect', function(){
    socket.emit('login', uid);
});

socket.on('new_msg', function(data){
    console.log('推送过来的消息:'+data);
});

6.php推送:
// 推送的url地址,使用自己的服务器地址
$push_api_url = "http://0.0.0.0:7064";
$post_data = array(
"type" => "publish",
"content" => "这个是推送的测试数据",
);
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $push_api_url );
curl_setopt ( $ch, CURLOPT_POST, 1 );
curl_setopt ( $ch, CURLOPT_HEADER, 0 );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_data );
curl_setopt ($ch, CURLOPT_HTTPHEADER, array("Expect:"));
$return = curl_exec ( $ch );
curl_close ( $ch );
var_export($return);

7.启动服务
cd到项目根目录
php server.php start 启动
php server.php stop 停止
php server.php restart 重启
php server.php status 当前服务状态

注意点:
一定要开放2120和7064端口,否则连接不了,会显示跨域,你也可以定义其他端口
项目根目录不是public,指的是public同级目录

926 1 2
1个评论

runtom

👍

  • 暂无评论

qdmdxgg

200
积分
0
获赞数
0
粉丝数
2023-05-25 加入
🔝