恩,又是即时聊天,基于swoole + redis的聊天室

广告---:工作室
浓浓年味小年夜,还在公司上班嘞,不过刚刚歇下,就把最近在看swoole写的聊天室奉上来,我这个人,对通信方面的学习与实践,一直是乐此不疲的。
基本功能:
 注册、登录、在线列表刷新、 群发、指定对象发
说明:我都是放在一个聊天控件里,没有把群聊和单聊分开,因为没那么多时间去做整合了。目前在考虑多去了解底层实现TCP、UDP服务器。
写的不好,多多见谅!

WebSocket服务器:

 

<?php


class WebSocket
{

    private $message = null;

    private $ws = null;

    private $usr_array = array();

    private $user_hash = "user_hash";

    private $conn_hash = "conn_hash";

    private $redis_conn = null;

    public function __construct()
    {
    //连接redis服务器 
        $this->redis_conn = new Redis();

        $this->redis_conn->connect('127.0.0.1', 6379);

        //创建websocket服务器对象,监听0.0.0.0:8000端口
        $this->ws = new swoole_websocket_server("0.0.0.0", 8000);

        //监听WebSocket连接打开事件
        $this->ws->on('open', function ($ws, $request) {

        });

        //监听WebSocket消息事件
        $this->ws->on('message', function ($ws, $obj) {
            echo "Message: {$obj->data}\n";

            $data_json = json_decode($obj->data, true);

            $this->message = $data_json['data'];

            switch ($data_json['code']) {
                case 1:
                    //s
                    $this->login($obj->fd);
                    break;
                case 2:
                    $this->sendMsg();
                    break;
                case 3:
                    $this->register($obj->fd);
                    break;
                default:
                    break;
            }
        });

        //监听WebSocket连接关闭事件
        $this->ws->on('close', function ($ws, $fd) {
            echo "client-{$fd} is closed\n";
            //刷新好友列表
    $this->redis_conn->hDel($this->conn_hash, $fd);
        $this->send(true, 0, $this->echoMsg(4, '', $this->all_in_line()));

        });

        $this->ws->start();

    }

 //用户注册
    private function register($id)
    {
        # phone,username,password 检测注册信息不得为空

        if (!$this->checkArray($this->message[0])) {
            $this->send(false, $id, $this->echoMsg(1000, 'have null data!', ''));
            return;
        }

        $user_phone = $this->message[0]['phone'];

        $user_array = array(
            "password" => $this->message[0]['password'],
            "username" => $this->message[0]['username']
        );

        if (!empty($this->getHash($this->user_hash, $user_phone))) {
            $this->send(false, $id, $this->echoMsg(1000, 'this phone is register!', ''));
        } else {
            $this->setHash($this->user_hash, $user_phone, serialize($user_array));
            $this->send(false, $id, $this->echoMsg(3, '', ''));
        }
    }

    private function login($id)
    {
        $psd = $this->message[0]['psd'];
        $usr = $this->message[0]['usr'];

        $in_res = $this->getHash($this->user_hash, $usr);
        if (empty($in_res)) {
            $this->send(false, $id, $this->echoMsg(1000, 'user not exist,please register!', $this->message));
        } else {
            $in_res = unserialize($in_res);
            if ($in_res['password'] == $psd) {

                //save user info
                $this->setHash($this->conn_hash, $id, $in_res['username']);

                $this->send(false, $id, $this->echoMsg(1, array("id" => $id, "username" => $in_res['username']), ''));

                //change friends item
                $this->send(true, 0, $this->echoMsg(4, '', $this->all_in_line()));
            } else {
                $this->send(false, $id, $this->echoMsg(1000, 'password is error!', ''));
            }
        }
    }

    //search all in line
    private function all_in_line()
    {
        $res = $this->redis_conn->hGetAll($this->conn_hash);
        return array($res);
    }


    // send msg
    private function send($is_all = false, $id = 0, $msg = '')
    {
        if ($is_all) {
            foreach ($this->ws->connections as $fd) {
                $this->ws->push($fd, $msg);
            }
        } else {
            $this->ws->push($id, $msg);
        }
    }

 //发送消息,并根据发送对象ID,如果为0则是发送给所有人
    private function sendMsg()
    {
        $send_id = intval($this->message[0]['to']);

        if ($send_id != 0) {
            //person

            $this->send(false, $send_id, $this->echoMsg(2, '', $this->message[0]));

        } else {
            //all
            $this->send(true, 0, $this->echoMsg(2, '', $this->message[0]));
        }

    }


    //返回json字符串
    private function echoMsg($code, $msg, $data)
    {
        $redata = array();
        //$data不为空
        if (!empty($data)) {
            if (is_array($data)) {//传入数组
                $redata = $data;
            } else {//传入字符串
                $redata = $data;
            }
        }
        if ($code == 0) {//识别码为0
            $reMsg = array('code' => $code, 'msg' => $msg);
            return json_encode($reMsg);
        } else {//识别码不为0
            $reMsg = array(
                'code' => $code,
                'msg' => $msg,
                'data' => $redata
            );
            return json_encode($reMsg);
        }
    }

    //save login state
    public function setHash($data = '', $key = '', $value = '')
    {
        # hash
        $in_login = $this->redis_conn->hGet($data, $key);
        if (empty($in_login)) {
            $this->redis_conn->hSet($data, $key, $value);
            return true;
        } else {
            return false;
        }
    }

    public function getHash($data = '', $key = '')
    {
        return $this->redis_conn->hGet($data, $key);
    }

    public function checkArray($data_array)
    {
        foreach ($data_array as $key => $value) {
            if (empty($value)) {
                return false;
            }
        }
        return true;
    }
}

new WebSocket();

然后是前端代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Hello , ChatRoom</title>
    <style>
        .a {
            margin-left: 10px;
        }

        .error {
            border: solid #ee0000 1px;
            border-radius: 3px;
            padding: 10px;
        }

        .chat_div {
            display: flex;
            flex-direction: row;
            height: 500px;
            min-width: 500px;
        }

        ul {
            list-style: none;
            margin: 10px;
        }

        li {

        }

        table {
            width: 95%;
            margin: 10px;
        }

        .chat_left {
            width: 30%;
            border: solid #ccc 1px;
        }

        .chat_right {
            width: 70%;
            border: solid #ccc 1px;
            overflow: hidden;
        }

        .chat_right_header {
            text-align: center;
            border-bottom: solid #ccc 1px;
            padding: 5px;
        }

        .chat_right_table {
            height: 60%;
            overflow: auto;
        }

        .chat_right_bottom {
            border-top: solid #ccc 1px;
            display: flex;
            justify-content: center;
            flex-direction: column;
            align-items: center;
        }

        .td_left {
            float: left;
        }

        .td_right {
            float: right;
        }

        textarea {
            width: 98%;
            height: 100px;
            margin: 10px;
        }

        td {
            padding: 10px;
        }

        .span_left {
            border: solid #66ccff 2px;
            background: #66ccff;
            border-radius: 3px;
            padding: 5px;
            color: #fff;
        }

        .span_right {
            border: solid #ee0000 2px;
            background: #ee0000;
            border-radius: 3px;
            padding: 5px;
            color: #fff;
        }

        .btn_send {
            float: right;
            margin: 0 0 0 0;
            width: 98%;
        }

        .send_obj {
            color: #ee0000;
        }
    </style>
</head>
<body>

<div class="error" style="display: none;">
    <span>error : not connect server ! now is restart ...<label style="color: #ee0000;margin-left: 10px;"
                                                                class="error_tips"></label></span>
    <p>
        <button οnclick="switch_tab(2)">close</button>
    </p>
</div>

<!--register page-->
<div class="register" style="display: none;">
    <h3>please register a count!</h3>
    <p><input type="text" placeholder="your phone" id="register_phone"></p>
    <p><input type="text" placeholder="your username" id="register_username"></p>
    <p><input type="password" placeholder="your password" id="register_password"></p>
    <p>
        <button οnclick="register()">register</button>
        <label class="a">have count?<a href="javascript:void(0)" class="a" οnclick="switch_tab(2)">go
            login</a></label></p>
</div>

<!--login page-->
<div class="login">
    <h3>please login!</h3>
    <p><input type="text" placeholder="phone" id="login_usernum"></p>
    <p><input type="password" placeholder="password" id="login_password"></p>
    <p>
        <button οnclick="login()">login</button>
        <label class="a">no count? <a href="javascript:void(0)" class="a" οnclick="switch_tab(1)">go
            register</a></label></p>
</div>

<div>
    <p id="res"></p>
</div>
<div>

</div>
<div>
    <div class="chat_header">

    </div>
    <div class="chat_div">
        <div class="chat_left">
            <ul class="friend_item">
            </ul>
        </div>

        <div class="chat_right">
            <div class="chat_right_header">
                Send To <span class="send_obj">all</span>
            </div>
            <div class="chat_right_table">
                <table>
                    <tbody>

                    </tbody>
                </table>
            </div>

            <div class="chat_right_bottom">
                <textarea placeholder="input" id="b"></textarea>
                <button class="btn_send" οnclick="sendMsg()">Send</button>
            </div>

        </div>
    </div>
</div>


<script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
    var is_conn = false;
    var websocket = null;
    var is_login = false;
    var usr = '';
    var i = 0;
    var re_time = null;
    var send_id = 0;
    var send_name = 'all';
    var me_id = 0;

    function init() {
        var wsServer = 'ws://192.168.146.132:8000';
        websocket = new WebSocket(wsServer);
        websocket.onopen = function (evt) {
            is_conn = true;
            console.log("Connected to WebSocket server.");
            if (re_time !== null) {
                clearInterval(re_time);
            }
            switch_tab(2);
        };

        websocket.onclose = function (evt) {
            console.log("Disconnected");
            switch_tab(4);
            is_conn = false;
            if (re_time === null) {
                re_time = setInterval(re_conn, 1000);
            }
        };

        websocket.onmessage = function (evt) {
            console.log('Retrieved data from server: ' + evt.data);

            var json_data = JSON.parse(evt.data);
            switch (json_data.code) {
                case 1:
                    // login success
                    is_login = true;
                    switch_tab(3);
                    usr = json_data.msg['username'];
                    me_id = json_data.msg['id'];

                    $(".chat_header").html("<h3 style='text-align: center;'>Welcome : " + usr + "</h3>");

                    console.log("This id is :" + me_id);
                    break;
                case 2:
                    // get message
                    if (json_data.data.from !== me_id) {
                        create_chat(true, json_data.data.from_name+"@"+json_data.data.to_name+" : ",json_data.data.msg);
                    }
                    break;
                case 3:
                    // register success
                    alert("register success!");
                    $("#register_phone").val("");
                    $("#register_username").val("");
                    $("#register_password").val("");
                    break;
                case 4:
                    //get all in line
                    create_friend_item(json_data.data);
                    break;

                case 1000:
                    $("#res").html("<p style='color: #ee0000;'>" + json_data.msg + "</p>");
                    break;
            }
        };

        websocket.onerror = function (evt, e) {
            console.log('Error occured: ' + evt.data);
        };
    }

    function register() {
        var register_json = {
            'code': 3,
            'msg': '',
            'data': [{
                'phone': $("#register_phone").val(),
                'username': $("#register_username").val(),
                'password': $("#register_password").val()
            }]
        };

        var json = JSON.stringify(register_json);

        websocket.send(json);
    }

    function login() {
        if (is_login) {
            alert("this window is login!");
        } else {
            var login_json = login_arr = {
                'code': 1,
                'msg': '',
                'data': [{
                    'psd': $("#login_password").val(),
                    'usr': $("#login_usernum").val()
                }]
            };

            var json = JSON.stringify(login_json);

            websocket.send(json);
        }
    }

    function sendMsg() {
        var send_msg = $("#b").val();
        if (send_msg) {
            var login_json = {
                'code': 2,
                'msg': '',
                'data': [{
                    'from': me_id,
                    'from_name':usr,
                    'to': send_id,
                    'to_name':send_name,
                    'msg': send_msg
                }]
            };

            var json = JSON.stringify(login_json);

            websocket.send(json);

            create_chat(false, "","@"+send_name+" "+send_msg);

            $("#b").val("");
        } else {
            alert("please input something");
        }
    }

    function create_friend_item(data) {
        $(".friend_item li").remove();

        $(".friend_item").append("<li><a href='javascript:void(0)' id='0'>all</a></li>");


        for (var i = 0; i < data.length; i++) {
            for (var key in data[i]) {
                if (parseInt(key) !== parseInt(me_id)) {
                    $(".friend_item").append("<li><a href='javascript:void(0)' id='" + key + "'>" + data[i][key] + "</a></li>");
                }
            }
        }


        $(".friend_item li a").click(function () {
            $(".send_obj").text($(this).text());
            send_id = parseInt($(this).attr("id"));
            send_name = $(this).text();
        });
    }
 //聊天后创建聊天消息列表
    function create_chat(left, title,msg) {
        if (left) {
            $("tbody").append("<tr><td class='td_left'>"+title+"<span class='span_left'>" + msg + "</span></td>/tr>")
        } else {
            $("tbody").append("<tr><td class='td_right'>"+title+"<span class='span_right'>" + msg + "</span></td>/tr>")
        }

        var root = document.getElementsByClassName("chat_right_table");
        //root.scrollIntoView(true);
    }

 //展示哪一个面板
    function switch_tab(res) {
        all_none();
        switch (res) {
            case 1:
                $(".register").css("display", 'block');
                break;
            case 2:
                $(".login ").css("display", 'block');
                break;
            case 3:
                $(".chat_div").css("display", 'flex');
                break;
            case 4:
                $(".error").css("display", 'block');
                break;
        }
    }
 //隐藏所以面板
    function all_none() {
        $(".register").css("display", 'none');
        $(".login").css("display", 'none');
        $(".chat_div").css("display", 'none');
        $(".error").css("display", 'none');
    }

    function re_conn() {
        i++;
        $(".error_tips").text(i);
        init();
    }

    //捕获文档对象的按键弹起事件
    $(document).keyup(function (e) {
        //按键信息对象以参数的形式传递进来了
        if (e.keyCode === 13) {
            //回车后
            sendMsg();
        }
    });

    init();

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


这样的话一个WebScoket聊天服务器和客户端就出来了,后续更改前端部分也就可以做成弹幕、互动等效果。swoole整块我还没看完,就先做了这个出来,后续看完还会再写其他内容。

很抱歉的是因为我在Ubuntu下写的代码,没有装中文输入法(有些部分是我写文章的时候添加注释),英语水平有点渣,影响阅读、敬请谅解!


广告---:工作室



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Auspicious5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值