欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

php加swoole加mysql 仿webqq及时聊天

程序员文章站 2022-04-19 12:41:47
...
本篇文章的内容是php加swoole加mysql 仿webqq及时聊天 ,现在分享给大家,有需要的朋友可以参考一下

一、效果图
php加swoole加mysql 仿webqq及时聊天
php加swoole加mysql 仿webqq及时聊天

二、目录结构
php加swoole加mysql 仿webqq及时聊天

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

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

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

三、数据库结构
php加swoole加mysql 仿webqq及时聊天

四、代码部分
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及时聊天 的详细内容,更多请关注其它相关文章!