swoole+thinkphp5搭建socket请求

本文详细介绍如何使用ThinkPHP框架结合Swoole扩展搭建实时通信服务。从源码下载到环境搭建,再到服务启动和前后端请求实现,最后通过实例验证WebSocket与AJAX数据交互效果。

目录

         1、下载源码

2、搭建环境

3、开启服务

4、websocket请求

5、ajax正常请求

6、验证


1、下载源码

源码地址:https://github.com/imgaoxianshen/swoole_thinkphp.git 

下载之后我更改以下两处代码 Application\index\controller\index.php 、server\ws.php  可以复制对应修改一下:      

<?php
namespace app\index\controller;
use app\common\lib\Util;
use app\common\lib\ali\Sms;

class Index
{
    public function index()
    {
        if(empty($_GET['game_id'])){
            return Util::show(config('code.error'),'error1');
        }
        if(empty($_GET['content'])){
            return Util::show(config('code.error'),'error2');
        }
        $data = [
            'user' => '用户'.rand(0,2000),
            'content' =>$_GET['content']
        ];
        foreach($_POST['http_server']->ports[1]->connections as $fd){
            $_POST['http_server']->push($fd,json_encode($data));
        }
        return Util::show(config('code.success'),'success',$data);
    }

    public function hello($name = 'ThinkPHP5')
    {
        return 'hello,' . $name;
    }

    public function sms(){
        try{
            $res = Sms::sendSms(15669762297,123456);
            dump($res);
        }catch(\Exception $e){
            echo $e->getMessage();
        }
    }
}
<?php
class Ws{
    CONST HOST = "0.0.0.0";
    CONST PORT = 9501;
    CONST CHART_PORT = 8812;
    public $ws = null;
    public function __construct(){
        $this->ws = new swoole_websocket_server(self::HOST,self::PORT);
        
        $this->ws->listen(self::HOST,self::CHART_PORT,SWOOLE_SOCK_TCP);

        $this->ws->set([
            'document_root' => "/home/root/default/swoole/public/static",
            'enable_static_handler' => true,
            'worker_num' => 5,
            'task_worker_num' =>4
        ]);
        $this->ws->on('start',[$this,'onStart']);
        $this->ws->on('workerstart',[$this,'onWorkerStart']);
        $this->ws->on('request',[$this,'onRequest']);
        $this->ws->on('open',[$this,'onOpen']);
        $this->ws->on('message',[$this,'onMessage']);
        $this->ws->on('task',[$this,'onTask']);
        $this->ws->on('finish',[$this,'onFinish']);
        $this->ws->on('close',[$this,'onClose']);
        $this->ws->start();
    }

    public function onWorkerStart(swoole_server $server,$worker_id){
        define("APP_PATH",__DIR__."/../application/");
        require __DIR__."/../thinkphp/start.php";
    }

    public function onStart($server){
        //进程名字
        swoole_set_process_name("live_master");
    }
    

    public function onRequest($request,$response){
        //防止谷歌浏览器默认访问图标
        if($request->server['request_uri'] =='/favicon.ico'){
            $response->status(404);
            $response->end();
            return;
        }
        $_SERVER = [];
        if(isset($request->server)){
            foreach($request->server as $k=>$v){
                $_SERVER[strtoupper($k)] = $v;
            }
        }
        if(isset($request->header)){
            foreach($request->header as $k=>$v){
                $_SERVER[strtoupper($k)] = $v;
            }
        }
        $_GET = [];
        if(isset($request->get)){
            foreach($request->get as $k=>$v){
                $_GET[$k] = $v;
            }
        }
        $_FILES = [];
        if(isset($request->files)){
            foreach($request->files as $k=>$v){
                $_FILES[$k] = $v;
            }
        }
        $_POST = [];
        if(isset($request->post)){
            foreach($request->post as $k=>$v){
                $_POST[$k] = $v;
            }
        }
        
        $_POST['http_server'] = $this->ws;
        //缓冲区
        ob_start();
        try{
            think\Container::get('app', [APP_PATH])
            ->run()
            ->send();
        }catch(\Exception $e){
            //todo
        }
        $res = ob_get_contents();
        ob_end_clean();
        $response->end($res);
    }

    public function onTask($serv,$taskId,$workerId,$data){
        //分发task任务 
        $obj = new \app\common\lib\task\Task;
        $method =  $data['method'];
        $flag = $obj->$method($data['data'],$serv);
        return $flag;
    }

    public function onFinish($serv, $task_id, $data){
        dump($data);
    }

    public function onOpen($ws,$req){
        //fd作为有序集合放入redis中
        var_dump($req->fd);
    }

    public function onMessage($ws,$frame){
        echo $frame->fd;
        $ws->push($frame->fd,"server-push");
    }

    public function onClose($ws,$fd){
        var_dump($fd);
    }
}

new Ws();

如果自己感兴趣可以参考以下视频教程自己亲自来搭建thinkphp5+swoole  

地址:https://pan.baidu.com/s/1-y5h1oI99z2afxiqc7YCcA 提取码: huy9 

2、搭建环境

条件不允许的情况下可以在自己的笔记本电脑上安装 vagrant+virturebox+lnmp+swoole,还有php的swoole拓展。(这一步就像自己搭建一个php的本地开发环境一样,自己亲手来搭建,这里就不做具体说明了)

3、开启服务

搭建好环境把第1步下载的文件放在你本地配置的虚拟机linux的自定义或者你想放的文件夹下。找到根目录的server这个文件夹下的ws.php文件,使用php ws.php命令来执行这个ws.php文件。

4、websocket请求

服务开启之后,在利用js写一个前端的websocket请求,我的本地html参考代码如下(ws://192.168.33.10:8812/?s=index/index/index这个地址可以根据你自己的请求url来更换)index.html

<html>
<head>
</head>
<body>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
// 初始化一个 WebSocket 对象

var wsObj = new WebSocket("ws://192.168.33.10:8812/?s=index/index/index");   //建立连接
    wsObj.onopen = function(){  //发送请求
        console.log("open");
        wsObj.send("Hello WebSocket");
    };
    wsObj.onmessage = function(ev){  //获取后端响应
        console.log(ev.data);
    };
    wsObj.onclose = function(ev){
        alert("close");
    };
    wsObj.onerror = function(ev){
        alert("error");
    };
</script>
</body>
</html>

5、ajax正常请求

在写一个前端请求后端接口的 ajax请求html,我的请求代码如下 request.html

<html>
<head>
</head>
<body>
   <button onclick='request()'>提交</button>
</body>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script type="text/javascript">
	function request(){
		$.ajax({
		    type:"POST",    //请求方式
		    url:"http://192.168.33.10:9501/index/index/index",
		    dataType:"jsonp",    //跨域json请求一定是jsonp
		    jsonp: "callbackparam",    //跨域请求的参数名,默认是callback
		    data:{'content':'ceshi','game_id':1},   //请求参数
		    beforeSend: function() {
		        //请求前的处理
		    },
		    success: function(data) {
		    	console.log(data);
		        //请求成功处理,和本地回调完全一样
		    },
		    complete: function() {
		        //请求完成的处理
		    },
		    error: function() {
		        //请求出错处理
		    }
		});
	}
</script>
</html>

6、验证

验证第5步ajax请求之后,websocket连接的页面是否会收到ajax请求传送的数据

 (1)打开index.html

(2)打开request.html

(3)打开index.html查看

ThinkPHP6 中集成 Swoole 扩展来实现 WebSocket 服务器,可以通过框架提供的命令和事件机制来完成。以下是实现步骤和相关说明: ### 1. 安装 Swoole 扩展 首先确保服务器环境中已经安装了 Swoole 扩展。如果尚未安装,可以通过 `composer` 来安装: ```bash composer require easyswoole/swoole ``` 或者使用 ThinkPHP 提供的 Swoole 包: ```bash composer require topthink/think-swoole ``` ### 2. 启动 Swoole 服务 ThinkPHP6 提供了内置的命令来启动 Swoole 服务。进入项目根目录后,执行以下命令: ```bash php think swoole start ``` 如果服务启动成功,可以通过浏览器访问 `IP+端口`(默认端口为 `80` 或 `0.0.0.0:80`)来测试服务是否正常运行。 ### 3. 配置 WebSocketThinkPHP6 的 Swoole 配置文件中,通常位于 `config/swoole.php`,需要启用 WebSocket 功能: ```php return [ // 开启 WebSocket 服务器 'websocket' => [ 'enable' => true, 'listen' => [ 'connect' => 'app\\listener\\WsConnect', 'close' => 'app\\listener\\WsClose', 'test' => 'app\\listener\\WsTest', ], ], ]; ``` ### 4. 创建事件监听器 ThinkPHP6 支持通过事件机制来处理 WebSocket 的连接、消息接收和断开事件。使用以下命令创建监听器: ```bash php think make:listener WsConnect php think make:listener WsClose php think make:listener WsTest ``` 创建完成后,监听器文件会生成在 `app/listener` 目录下。例如,`WsTest` 事件监听器可以处理自定义消息类型: ```php namespace app\listener; use think\swoole\Websocket; class WsTest { public function handle($event) { // 接收到的消息内容 $data = $event->data; echo "接收到消息: " . json_encode($data) . PHP_EOL; // 向客户端发送响应 Websocket::emit('callback', '服务器收到消息: ' . json_encode($data)); } } ``` ### 5. 处理连接和断开事件 在 `WsConnect` 和 `WsClose` 监听器中,可以分别处理客户端连接和断开的逻辑: #### `WsConnect` 示例 ```php namespace app\listener; use think\swoole\Websocket; class WsConnect { public function handle($event) { echo "客户端已连接: {$event->fd}" . PHP_EOL; Websocket::emit('welcome', '欢迎连接到 WebSocket 服务器'); } } ``` #### `WsClose` 示例 ```php namespace app\listener; use think\swoole\Websocket; class WsClose { public function handle($event) { echo "客户端已断开连接: {$event->fd}" . PHP_EOL; } } ``` ### 6. 测试 WebSocket 服务 启动服务后,可以使用 WebSocket 客户端进行测试。例如,在浏览器控制台中执行以下代码: ```javascript const ws = new WebSocket('ws://127.0.0.1:9501'); ws.onopen = function() { console.log('连接已建立'); ws.send('Hello Server'); }; ws.onmessage = function(event) { console.log('收到消息:', event.data); }; ws.onclose = function() { console.log('连接已关闭'); }; ``` ### 7. 多应用模式下的 WebSocket 如果项目采用多应用模式,可以在对应的应用目录下创建监听器。例如,在 `app/index/listener` 中创建 `WebsocketTest.php`: ```php namespace app\index\listener; use think\Container; use think\swoole\Websocket; class WebsocketTest { public $websocket = null; public function __construct(Container $container) { $this->websocket = $container->make(Websocket::class); } public function handle($event) { echo "接收到事件: {$event->type} --- " . json_encode($event->data) . PHP_EOL; $func = $event->type; $this->$func($event); } public function test($event) { $msg = json_encode($event->data, JSON_UNESCAPED_UNICODE); $this->websocket->emit('callback', $msg); } } ``` ### 8. 注意事项 - 确保 `config/swoole.php` 中的 `websocket` 配置正确,尤其是监听事件的命名空间路径。 - 在多应用模式下,需注意监听器的命名空间与实际文件路径的匹配。 - 如果 `php think swoole` 命令失效,可以直接使用 PHP 启动 Swoole 服务: ```bash php think swoole start ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值