前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >swoole框架-swoft实现程圣母与云天明对话功能启动ws服务创建http服务的聊天控制器创建视图文件创建ws控制器结果演示

swoole框架-swoft实现程圣母与云天明对话功能启动ws服务创建http服务的聊天控制器创建视图文件创建ws控制器结果演示

作者头像
章鱼喵
发布2018-08-02 15:15:33
6660
发布2018-08-02 15:15:33
举报
文章被收录于专栏:codingcoding

当万有引力号启动广播按钮,向宇宙发送三体星的坐标时,地球已经失去了任何侵略价值。三体人将所有在地球的资源全部撤走,但在临别时,安排了程圣母与云天明的远程会话。接下来,我们用swoft来实现他们两人的聊天功能。

光年之外的对话

PHP果真是宇宙最强的语言,星际通话也能办到...

对swoft不了解的同学请看 swoole框架-swoft初体验

启动ws服务

代码语言:javascript
复制
☁  swoft [master] ⚡ sudo php bin/swoft ws:start
Password:
                                 Server Information
************************************************************************************
* WS   | host: 0.0.0.0, port: 80, type: 1, worker: 1, mode: 3 (http is Enabled)
* TCP  | host: 0.0.0.0, port: 8099, type: 1, worker: 1 (Enabled)
************************************************************************************
Server has been started. (master PID: 3954, manager PID: 3955)
You can use CTRL + C to stop run.

创建http服务的聊天控制器

swoft 提供了生成控制器文件的命令行

代码语言:javascript
复制
☁  swoft [master] ⚡ php bin/swoft gen:controller chat --prefix /chat -y

Class data:
{
    "name": "chat",
    "suffix": "Controller",
    "namespace": "App\\Controllers",
    "className": "ChatController",
    "prefix": "/chat",
    "idVar": "{id}"
}

swoft/app/Controllers/ChatController.php

代码语言:javascript
复制
<?php
namespace App\Controllers;

use Swoft\Http\Server\Bean\Annotation\Controller;
use Swoft\Http\Server\Bean\Annotation\RequestMapping;
use Swoft\Http\Server\Bean\Annotation\RequestMethod;

/**
 * Class ChatController
 * @Controller(prefix="/chat")
 * @package App\Controllers
 */
class ChatController{
    /**
     * @RequestMapping(route="/chat/{uid}", method=RequestMethod::GET)
     * @param int $uid
     * @return \Swoft\Http\Message\Server\Response|\think\response\View
     */
    public function index(int $uid)
    {
        $users = [
            1 => '程心',
            2 => '云天明',
        ];
        $receiveUid = $uid == 1 ? 2 : 1;
        $userName = $users[$uid];
        $data = compact('uid', 'userName', 'receiveUid');
        return view('chat/index', $data);
    }
}

创建视图文件

视图文件用vue.js搭建,对于vue.js不熟悉的同学,参见 实例学习vue.js目录

swoft/resources/views/chat/index.php

代码语言:javascript
复制
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.1.0/css/bootstrap.min.css">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<style>
    .container {
        margin-top: 2%;
    }
</style>
<body>
<div class="container">
    <div id="app">
        <h3 class="offset-md-3">{{ userName }}</h3>
        <div class="alert alert-warning col-sm-7">
            <strong>警告!</strong> 你们的聊天信息已经被全程监控...
        </div>
        <div v-for="(value, key) in list" :class="className(value.uid)" >
            {{ value.content }}
        </div>
        <div>
            <form action="" method="post" class="form-horizontal" role="form">
                <div class="form-group">
                    <div class="col-sm-8">
                        <input type="text" class="form-control" placeholder="远在光年之外的你们,想聊些什么呢..." v-model="content" required="required">
                    </div>
                </div>
                <button type="submit" class="btn btn-info offset-md-6" @click.prevent="pushData">发送</button>
            </form>
        </div>
    </div>
</div>
<script>
    let ws = new WebSocket('ws://127.0.0.1/chat')
    ws.onopen = function() {
        let data = {
            'sendUid': vm.$data.uid,
            'type': 'bind',
            'receiveUid': '',
        }
        // 将uid推送到服务端,与fd进行绑定
        ws.send(JSON.stringify(data));
    }
    ws.onmessage = function(evt) {
        let data = JSON.parse(evt.data)
        if (data.content) {
            vm.$data.list.push(data)
        }
    }
    ws.onclose = function() {
        console.log('连接关闭')
    }

    let vm = new Vue({
        el: "#app",
        data: {
            list: [],
            content: '',
            uid: <?=$uid?>,
            receiveUid: <?=$receiveUid?>,
            userName: '<?=$userName?>',
        },
        methods: {
            className(uid) {
                if (uid === this.uid) {
                    return 'alert alert-success col-md-2'
                } else {
                    return 'alert alert-danger col-md-2 offset-md-5'
                }
            },
            pushData() {
                let data = {
                    'sendUid': this.uid,
                    'receiveUid': this.receiveUid,
                    'content': this.content,
                    'type': 'chat'
                }
                ws.send(JSON.stringify(data));
                this.content = ''
            }
        },

    })
</script>
</body>
</html>

创建ws控制器

代码语言:javascript
复制
☁  swoft [master] ⚡ php bin/swoft gen:websocket chat --prefix /chat

Class data:
{
    "name": "chat",
    "suffix": "Controller",
    "namespace": "App\\WebSocket",
    "className": "ChatController",
    "prefix": "/chat"
}
代码语言:javascript
复制
<?php

namespace App\WebSocket;

use Swoft\Http\Message\Server\Request;
use Swoft\Http\Message\Server\Response;
use Swoft\WebSocket\Server\Bean\Annotation\WebSocket;
use Swoft\WebSocket\Server\HandlerInterface;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;

/**
 * Class ChatController - This is an controller for handle websocket
 * @package App\WebSocket
 * @WebSocket("chat")
 */
class ChatController implements HandlerInterface
{
    /**
     * @param Request $request
     * @param Response $response
     * @return array
     * [
     *  self::HANDSHAKE_OK,
     *  $response
     * ]
     */
    public function checkHandshake(Request $request, Response $response): array
    {
        return [self::HANDSHAKE_OK, $response];
    }

    /**
     * @param Server $server
     * @param Request $request
     * @param int $fd
     * @return mixed
     */
    public function onOpen(Server $server, Request $request, int $fd)
    {
    }

    /**
     * @param Server $server
     * @param Frame $frame
     * @return mixed
     */
    public function onMessage(Server $server, Frame $frame)
    {
        $fd = $frame->fd;
        $data = json_decode($frame->data, true);
        if ($data['type'] == 'bind') {
            // 将uid与fd绑定
            $server->bind($fd, $data['sendUid']);
        }
        $start_fd = 0;
        while(true)
        {
            // 获取所有fd连接
            $conn_list = $server->getClientList($start_fd, 10);
            if ($conn_list === false or count($conn_list) === 0)
            {
                break;
            }
            $start_fd = end($conn_list);
            foreach($conn_list as $v)
            {
                // 根据fd获取uid
                $connection = $server->connection_info($v);
                if (isset($connection['uid']) && in_array($connection['uid'], [$data['receiveUid'], $data['sendUid']])) {
                    if (isset($data['content'])) {
                        $response = [
                            'type' => 'response',
                            'content' => $data['content'],
                            'uid' => $data['receiveUid'],
                        ];
                        if ($v != $fd) { // 避免重复发送给消息发起者的fd
                            $server->push($v, json_encode($response, true));
                        }
                    }
                }
            }
        }
        // 推送消息给客户端
        \Swoft::$server->sendTo($fd, $frame->data);
    }

    /**
     * @param Server $server
     * @param int $fd
     * @return mixed
     */
    public function onClose(Server $server, int $fd)
    {
        // do something. eg. record log
    }
}

结果演示

建议同时多开几个浏览器窗口,访问http://127.0.0.1/chat/1http://127.0.0.1/chat/2

切换窗口进行消息发送,观察其他窗口的数据变动

程心与云天明对话.gif

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.08.01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 启动ws服务
  • 创建http服务的聊天控制器
  • 创建视图文件
  • 创建ws控制器
  • 结果演示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档