• 技术文章 >后端开发 >php教程

    php加swoole加mysql 仿webqq及时聊天

    不言不言2018-04-09 15:40:10原创1920
    本篇文章的内容是php加swoole加mysql 仿webqq及时聊天 ,现在分享给大家,有需要的朋友可以参考一下

    一、效果图

    php入门到就业线上直播课:进入学习


    二、目录结构

    images : 存放图片
    js : js文件
    swoole

    |----action.php     数据库操作类
    |----config.php     数据库配置文件
    |----websocket.php     swoole创建websocket协议文件

    index.php : 聊天首页
    login.html : 登录页面
    webqq.sql : SQL数据库文件

    三、数据库结构

    四、代码部分
    4.1、config.php 数据库配置文件

    <?php
    $database = array(
        'host'=>'127.0.0.1',
        'user'=>'root',
        'password'=>'4f54dd',
        'port'=>3306,
        'database'=>'webqq',
        'charset'=>'utf8'
    );

    4.2、action.php数据库操作类

    <?php
    class Action
    {
        private $conn;
        public function __construct()
        {
            require_once (__DIR__.'/config.php');
            $this->conn = mysqli_connect($database['host'],$database['user'],$database['password'],$database['database']) or die ('Connect mysql failed ~~'.mysqli_connect_error());
        }
    
        //login
        public function login($nickname,$username,$password)
        {
            session_start();
            $sql = " select `id` from `users` where `username` = '{$username}' ";
            if($query = $this->conn->query($sql)) {
                $row = mysqli_fetch_assoc($query);
                $now = date('Y-m-d H:i:s');
                if($row['id']) {
                    $sql = " update `users` set `nickname` = '{$nickname}' , `username` = '{$username}' ,`password` = md5('{$password}') , `login_time` = '{$now}' , `login_num` = (`login_num` + 1) where `id` = {$row['id']} ";
                } else {
                    $sql = " insert into `users` (`nickname`,`username`,`password`,`login_time`,`login_num`) values ('{$nickname}' , '{$username}' , md5('{$password}') , '{$now}' ,'1')";
                }
                $this->conn->query($sql);
                $user_id = $this->conn->insert_id;
                $_SESSION['uid'] = $row['id'] ? $row['id'] :  $user_id;
                $_SESSION['nickname'] = $nickname;
                return 1;
            } else {
                return 0;
            }
        }
    
        //add friend
        public function addFriend($from_uid,$to_uid)
        {
            $sql = " select * from `friend` where `from_uid` = '{$from_uid}' and `to_uid` = '{$to_uid}' ";
            if($query = $this->conn->query($sql)) {
                $is_friend = mysqli_fetch_assoc($query);
                if(!$is_friend['to_uid']){
                    if($from_uid == $to_uid) {
                        return 2;
                    } else {
                        $sql = " select `nickname` from `users` where `id` = '{$to_uid}' ";
                        $query = $this->conn->query($sql);
                        $ret = mysqli_fetch_assoc($query);
                        $nickname = $ret['nickname'];
                        if($nickname){
                            $sql = " insert into `friend` (`from_uid`,`to_uid`,`nickname`) values ('{$from_uid}','{$to_uid}','{$nickname}') ";
                            $this->conn->query($sql);
                            return array('to_uid'=>$to_uid,'nickname'=>$nickname);
                        } else {
                            return 3;
                        }
                    }
                } else {
                    return 4;
                }
            } else {
                return 0;
            }
        }
    
        //friend lists
        public function friendLists($from_uid)
        {
            $sql = " select `id`,`nickname` from `users` where `id` != '{$from_uid}' ";
            if($query = $this->conn->query($sql)) {
                $lists = [];
                while ($row = mysqli_fetch_assoc($query)) {
                    $sql_1 = " select `fd` from `fd_tmp` where `uid` = '{$row['id']}' ";
                    $query_1 = $this->conn->query($sql_1);
                    $ret = mysqli_fetch_assoc($query_1);
                    $row['status'] = $ret['fd'] ? 'online' : 'offline' ;
                    $lists[] = $row;
                }
                return $lists;
            } else {
                return 0;
            }
        }
    
    
        //load history message
        public function loadHistory($from_uid,$to_uid)
        {
            $sql = " select `from_uid`,`to_uid`,`message`,`send_time` from `chat` where  ( (`from_uid` = '{$from_uid}' and `to_uid` = '{$to_uid}') or (`to_uid` = '{$from_uid}' and `from_uid` = '{$to_uid}') ) order by `send_time` desc";
            if($query = $this->conn->query($sql)) {
                $message = [];
                while ($row = mysqli_fetch_assoc($query)) {
                    $message[] = $row;
                }
                return $message;
            } else {
                return 0;
            }
        }
    
        //send message
        public function sendMessage($from_uid,$to_uid,$message)
        {
            $time = date('Y-m-d H:i:s');
            $sql = " insert into `chat` (`from_uid`,`to_uid`,`message`,`send_time`) values ('{$from_uid}','{$to_uid}','{$message}','{$time}') ";
            if($query = $this->conn->query($sql)) {
                $last_id = $this->conn->insert_id;
                return $last_id;
            } else {
                return 0;
            }
        }
    
        //get fd 
        public function getFd($uid)
        {
            $sql = " select `fd` from `fd_tmp` where `uid` = '{$uid}' ";
            if($query = $this->conn->query($sql)) {
                $row = mysqli_fetch_assoc($query);
                return $row['fd'] ? $row['fd'] : 0;
            } else {
                return 0;
            }
        }
    
        //bind fd 
        public function bindFd($uid,$fd)
        {
            $sql = " insert into `fd_tmp` (`fd`,`uid`) values ('{$fd}','{$uid}') ";
            if($this->conn->query($sql)) {
                return $fd;
            } else {
                return 0;
            }
        }
    
        //unbind fd 
        public function unbindFd($fd)
        {
            $sql = " delete from `fd_tmp` where `fd` = '{$fd}' ";
            if($this->conn->query($sql)) {
                return 1;
            } else {
                return 0;
            }
        }
    
        public function __destruct()
        {
            mysqli_close($this->conn);
        }
    }
    
    //process ajax request
    if($_POST && isset($_POST['typ']))
    {
        $action = new Action();
        switch ($_POST['typ']) {
            case 'login':
                $ret = $action->login($_POST['nickname'],$_POST['username'],$_POST['password']);
                break;
            case 'addFriend':
                $ret = $action->addFriend($_POST['from_uid'],$_POST['to_uid']);
                break;
            case 'friendLists':
                $ret = $action->friendLists($_POST['from_uid']);
                break;
            case 'loadHistory':
                $ret = $action->loadHistory($_POST['from_uid'],$_POST['to_uid']);
                break;
            case 'sendMessage':
                $ret = $action->sendMessage($_POST['from_uid'],$_POST['to_uid'],$_POST['message']);
                break;
        }
        echo json_encode(array('data'=>$ret));
    }

    4.3、websocket.php文件

    <?php
    require_once(__DIR__.'/action.php');
    new Websocket();
    class Websocket
    {
        private $serv;
        private $action;
    
        public function __construct()
        {
            $this->action = new action();
            $this->serv = new swoole_websocket_server('0.0.0.0',9502);
            $this->serv->on('open',array($this,'onOpen'));
            $this->serv->on('message',array($this,'onMessage'));
            $this->serv->on('close',array($this,'onClose'));
            $this->serv->start();
        }
    
        public function onOpen($server,$request)
        {
            echo "Welcome {$request->fd} \n";
        }
    
        public function onMessage($server,$request)
        {
            $data = json_decode($request->data);
            $from_uid = $data->from_uid;
            $to_uid = $data->to_uid;
            $message = $data->message;
            $this->action->unbindFd($from_uid);
            $from_fd = $this->action->bindFd($from_uid,$request->fd);
            if($from_fd) {
                $to_fd = $this->action->getFd($to_uid);
                if($to_fd) {
                    $server->push($to_fd,$message);
                } 
            } else {
                $server->push($request->fd,'bind from_fd failed ~~');
            }
        }
    
        public function onClose($server,$fd)
        {
            $this->action->unbindFd($fd);
            echo "Goodbye {$fd} \n";
        }
    }

    4.4、index.php首页聊天文件

    <?php
    session_start();
    if(!$_SESSION['nickname'] && !$_SESSION['uid']){
        echo '<script>window.location.href="login.html";</script>';
    }
    ?>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="apple-touch-fullscreen" content="yes" />
        <meta name="format-detection" content="telephone=no"/>
        <meta name="apple-mobile-web-app-status-bar-style" content="black" />
        <META HTTP-EQUIV="pragma" CONTENT="no-cache"> 
    <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate"> 
    <META HTTP-EQUIV="expires" CONTENT="0">
        <meta name="format-detection" content="telephone=no" />
        <meta name="msapplication-tap-highlight" content="no" />
        <meta name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1" />
        <title>webqq----swoole</title>
        <script type="text/javascript" src="js/jquery.js"></script>
        <style type="text/css">
        html,body{margin:0;padding: 0;background-color: #eee;background-image: url("./images/1.jpg") }
        .userlists{width:280px;height: 620px;border:1px #222 solid;box-shadow:3px 3px 10px #222;border-radius:5px;margin:100px 0px 0px 100px;background-color: #fff}
        .userlists-title{background-color: #222;color:#fff;height: 50px;padding-top:10px;text-align: center;border-radius: 5px 5px 0px 0px;position: relative;}
        .lists_left{height: 500px;overflow-y:scroll;}
        .lists_left::-webkit-scrollbar {display:none}
        .lists_left ul,li{margin:0px;padding:0px;list-style: none}
        .lists_left li{border-bottom:  1px #666 solid;height: 35px;line-height: 35px;}
        .lists_left li a{text-decoration: none;color:#000;height: 100%;display: block;padding-left: 10px}
        .tools{border-radius: 0px 0px 5px 5px;}
        .h10{height: 10px;}
        .h30{height: 500px}
        .circular{height: 30px;width: 30px;border-radius: 30px;background-color: #fff;margin:0 auto;}
        .find{height: 40px;line-height:40px;text-align:center;background-color: #ccc}
        .find input{outline: none}
        .dialogue{width: 600px;height: 600px;background-color: #fff;position: absolute;top:100px;left: 450px;border-radius: 5px;border:1px #222 solid;box-shadow:3px 5px 5px #222;border-radius:5px;display: none;}
        .close{border:1px #fff solid;border-radius:5px;display: inline-block;width: 50px;height: 25px;line-height: 25px;position: absolute;right: 15px;top:12px;}
        .send{height: 50px;line-height: 50px;background-color: #222;border-radius: 0px 0px 5px 5px;text-align: center; }
        .send input[name='content']{height: 30px;width:480px;padding:0px 5px;outline: none}
        .send input[name='sendBtn']{height: 34px;width:80px;display: inline-block;}
        .chat-line{width:360px;border-radius: 10px;margin:10px;padding: 10px;word-wrap:break-word}
        .from{border:1px red solid;float: right;}
        .to{border:1px green solid;float: left;}
        .all{position: absolute;top:0;right: 100px}
        .scroll_box{position: relative;overflow-y:scroll;height: 500px};
        .scroll_box::-webkit-scrollbar {display:none}
        .lists  {position: absolute;left: 0;top: 0;}
    
        </style>
    </head>
    <body>
        <p class="userlists">
            <p class="userlists-title"><?php echo $_SESSION['nickname'];?><br>好友列表</p>
            <p class="lists_left">
                <ul id="friend_lists">
                </ul>
            </p>
            <p class="userlists-title tools"><p class="h10"></p><p class="circular"></p></p>
        </p>
    
        <p class="dialogue">
            <p class="userlists-title">正在与 <t id="uname">.....</t> 聊天 <span class="close">关闭</span></p>
            <p class="scroll_box">
                <p class="lists " id="chat-box">
                </p>
            </p>
            <p class="send">
                <input type="hidden" name="to_uid" >
                <input type="text" name="content" placeholder="发送内容">
                <input type="button" name="sendBtn" id="sendMessage" value="发送">
            </p>
        </p>
    
    
    
        <script type="text/javascript">
            $(function(){
                $.post("./swoole/action.php",{from_uid:<?php echo $_SESSION['uid'];?>,typ:'friendLists'},function(res){
                    var r = eval("(" + res + ")");
                    if(r.data) {
                        var h = "";
                        for(var i = 0; i< r.data.length; i++) {
                            var status = r.data[i].status =="offline" ? "离线" : "在线" ; 
                            h += '<li><a data-id="' + r.data[i].id + '" data-nickname="' + r.data[i].nickname + '" class="friend" href="javascript:;">' +  r.data[i].nickname + " &nbsp;( " + status +' ) </a></li>';
                        }
                        $("#friend_lists").html(h);
                    }
                });
    
    
                $("#friend_lists").on("click",".friend",function(){
                    var to_uid = $(this).attr("data-id");
                    var nickname = $(this).attr("data-nickname");
                    $("#uname").html(nickname);
                    $("input[name='to_uid']").val(to_uid);
                    $.post("./swoole/action.php",{from_uid:<?php echo $_SESSION['uid'];?>,to_uid:to_uid,typ:"loadHistory"},function(res){
                        var r = eval("(" + res + ")");
                        if(r.data) {
                            var h = "";
                            for (var i = r.data.length - 1; i >= 0; i--) {
                                if(r.data[i].from_uid == <?php echo $_SESSION['uid'];?>) {
                                    h += '<p class="chat-line from">' + r.data[i].message + '</p>';
                                } else {
                                    h += '<p class="chat-line to">' + r.data[i].message + '</p>';
                                }
                            }
                            $("#chat-box").html(h);
                            srcollBox()
                        }
                    });
                    $(".dialogue").show();
                    
    
                });
    
                $("#sendMessage").on("click",function(){
                    if($("input[name='content']").val()) {
                        srcollBox()
                        sendMessage();
    
                    } else {
                        alert("please input your message~");
                    }
                    
                });
                $(document).keyup(function(evt){
                    if(evt.keyCode == 13) {
                        if($("input[name='content']").val()) {
                            srcollBox()
                            sendMessage();
                        } else {
                            alert("please input your message~");
                        }
                    }
                });
    
                $(".close").on("click",function(){
                    $(".dialogue").hide();
                });
                function srcollBox(){
                    var h = $(".lists").height();
                    $(".scroll_box").scrollTop(h,4000)
                }
                srcollBox();
    
                if(window.WebSocket){
                    var ws = new WebSocket("ws://192.168.0.140:9502");
                    ws.onopen = function(evt){
                        console.log("Connect WebSocket succuess ~~ \n");
                    }
                    ws.onmessage = function(evt){
                        $("#chat-box").append('<p class="chat-line to">' + evt.data + '</p>');
                        srcollBox();
                        console.log("message on server : " + evt.data + "\n");
                    }
                    ws.onclose = function(evt){
                        console.log("WebSocket closed ~~\n");
                    }
                    ws.onerror = function(evt){
                        console.log("Connect WebSocket failed ~~\n");
                    }
                    function sendMessage(){
                        var params = {
                            from_uid : <?php echo $_SESSION['uid'];?>,
                            to_uid : $("input[name='to_uid']").val(),
                            message : $("input[name='content']").val(),
                            typ : "sendMessage"
                        };
                        var msg = JSON.stringify(params);
                        $("#chat-box").append('<p class="chat-line from">' + $("input[name='content']").val() + '</p>');
                        srcollBox();
                        $.post("./swoole/action.php",params,function(res){
                            var r = eval("(" + res + ")");
                            if(r.data) {
                                ws.send(msg);
                            } else {
                                alert("send message failed , insert mysql failed~~\n");
                            }
                        });
                        
                    }
                } else {
                    alert("Your browser does not support WebSocket !");
                }
            });
        </script>
    </body>
    </html>

    4.5、login.html 登录文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="apple-touch-fullscreen" content="yes" />
        <meta name="format-detection" content="telephone=no"/>
        <meta name="apple-mobile-web-app-status-bar-style" content="black" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="msapplication-tap-highlight" content="no" />
        <meta name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1" />
        <title>webqq----swoole</title>
        <script type="text/javascript" src="./js/jquery.js"></script>
        <style type="text/css">
        html,body{margin:0;padding: 0;background-color: #eee}
        .login-form{background-color: #fff;width: 500px;height: 500px;margin:100px auto;border:1px #ccc solid;border-radius: 5px;box-shadow: 3px 3px 3px #666}
        h3{text-align: center;margin-top: 100px}
        .container{text-align: center;margin-top: 30px;}
        .container label{display: inline-block;width: 50px;}
        .container input{display: inline-block;height: 25px;line-height: 25px;padding: 0px 5px;width: 300px;outline: none}
        input[name='login']{background-color: #5aba1f;color:#fff;border:none;width: 150px;height: 30px;line-height: 30px;border-radius: 5px;margin-top: 30px;cursor: pointer;}
        .warning{border:2px #f00 solid;}
        </style>
    </head>
    <body>
    
        <form method="post" action="" class="login-form">
            <h3>WebQQ</h3>
            <p class="container"><label>昵称:</label><input type="text" name="nickname" placeholder="昵称" ></p>
            <p class="container"><label>帐号:</label><input type="text" name="username" placeholder="用户"></p>
            <p class="container"><label>密码:</label><input type="password" name="password" placeholder="密码"></p>
            <p class="container"><input type="button" name="login" value="登录"></p>
        </form>
        <script type="text/javascript">
            $(function(){
                $("input[name='login']").click(function(){
                    var nickname = $("input[name='nickname']").val();
                    var username = $("input[name='username']").val();
                    var password = $("input[name='password']").val();
                    if(nickname == ""){
                        alert("请设置昵称");
                        $("input[name='nickname']").focus();
                        $("input[name='nickname']").addClass("warning");
                        $("input[name='username']").removeClass("warning");
                        $("input[name='password']").removeClass("warning");
                    } else if(username == "") {
                        alert("请输入帐号");
                        $("input[name='username']").focus();
                        $("input[name='nickname']").removeClass("warning");
                        $("input[name='username']").addClass("warning");
                        $("input[name='password']").removeClass("warning");
                    } else if(password == "") {
                        alert("请输入密码");
                        $("input[name='password']").focus();
                        $("input[name='nickname']").removeClass("warning");
                        $("input[name='username']").removeClass("warning");
                        $("input[name='password']").addClass("warning");
                    } else {
                        $("input[name='nickname']").removeClass("warning");
                        $("input[name='username']").removeClass("warning");
                        $("input[name='password']").removeClass("warning");
                        $.post("./swoole/action.php",{nickname:nickname,username:username,password:password,typ:'login'},function(res){
                            var r = eval("(" + res + ")");
                            if(r.data == "1"){
                                window.location.href="index.php";
                            } else {
                                alert("failed~~");
                            }
                        });
                    }
                });
            });
        </script>
    </body>
    </html>

    4.6、webqq.sql 数据结构文件

    -- Adminer 4.1.0 MySQL dump
    
    SET NAMES utf8;
    SET time_zone = '+00:00';
    SET foreign_key_checks = 0;
    SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
    
    DROP TABLE IF EXISTS `chat`;
    CREATE TABLE `chat` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
      `from_uid` int(10) unsigned NOT NULL,
      `to_uid` int(10) unsigned NOT NULL,
      `message` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
      `send_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
    
    
    DROP TABLE IF EXISTS `fd_tmp`;
    CREATE TABLE `fd_tmp` (
      `fd` int(10) unsigned NOT NULL,
      `uid` int(10) unsigned NOT NULL
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='FD值与用户ID绑定';
    
    
    DROP TABLE IF EXISTS `friend`;
    CREATE TABLE `friend` (
      `from_uid` int(10) unsigned DEFAULT NULL,
      `to_uid` int(10) unsigned NOT NULL,
      `nickname` varchar(45) COLLATE utf8_unicode_ci NOT NULL
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='好友列表';
    
    
    DROP TABLE IF EXISTS `users`;
    CREATE TABLE `users` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
      `nickname` varchar(45) COLLATE utf8_unicode_ci NOT NULL COMMENT '昵称',
      `username` varchar(45) COLLATE utf8_unicode_ci NOT NULL COMMENT '登陆名称',
      `password` char(32) COLLATE utf8_unicode_ci NOT NULL COMMENT '登陆密码',
      `login_time` datetime NOT NULL COMMENT '最后登陆时间',
      `login_num` int(10) unsigned DEFAULT '0' COMMENT '登陆次数',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='用户列表';
    
    
    -- 2018-03-27 10:05:35

    4.7、服务器环境centos7 + mariadb + swoole + apache + php7
    注意事项:须安装swoole扩展,Linux服务器,PHP7+版本以上
    进行项目根目录使用: php websocket.php 执行该文件

    源码下载地址:https://pan.baidu.com/s/1sWY-...

    以上就是php加swoole加mysql 仿webqq及时聊天 的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。

    千万级数据并发解决方案(理论+实战):点击学习

    Mysql单表千万级数据量的查询优化与性能分析

    Mysql主从原理及其在高并发系统中的应用

    专题推荐:swoole webqq mysql
    上一篇:浅谈PHP面向对象编程 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• 详解PHP会话如何实现在30分钟后被销毁(附代码实例)• PHP中全面阻止SQL注入式攻击分析小结_PHP教程• 一棵php的类树(支持无限分类)_PHP教程• php 不使用js实现页面跳转_php技巧• 用PHP将数据导入到Foxmail的实现代码_php技巧
    1/1

    PHP中文网