一、效果图

二、目录结构

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());}//loginpublic 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 friendpublic 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 listspublic 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 messagepublic 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 messagepublic 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><div class="userlists"><div class="userlists-title"><?php echo $_SESSION['nickname'];?><br>好友列表</div><div class="lists_left"><ul id="friend_lists"></ul></div><div class="userlists-title tools"><div class="h10"></div><div class="circular"></div></div></div><div class="dialogue"><div class="userlists-title">正在与 <t id="uname">.....</t> 聊天 <span class="close">关闭</span></div><div class="scroll_box"><div class="lists " id="chat-box"></div></div><div class="send"><input type="hidden" name="to_uid" ><input type="text" name="content" placeholder="发送内容"><input type="button" name="sendBtn" id="sendMessage" value="发送"></div></div><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 += '<div class="chat-line from">' + r.data[i].message + '</div>';} else {h += '<div class="chat-line to">' + r.data[i].message + '</div>';}}$("#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('<div class="chat-line to">' + evt.data + '</div>');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('<div class="chat-line from">' + $("input[name='content']").val() + '</div>');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><div class="container"><label>昵称:</label><input type="text" name="nickname" placeholder="昵称" ></div><div class="container"><label>帐号:</label><input type="text" name="username" placeholder="用户"></div><div class="container"><label>密码:</label><input type="password" name="password" placeholder="密码"></div><div class="container"><input type="button" name="login" value="登录"></div></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 dumpSET 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及时聊天相关推荐

  1. php mysql qq登录_php+swoole+mysql 仿webqq及时聊天

    一.效果图 二.目录结构 images : 存放图片 js : js文件 swoole |----action.php 数据库操作类 |----config.php 数据库配置文件 |----webs ...

  2. Java+Swing+mysql仿QQ聊天工具

    Java+Swing+mysql仿QQ聊天工具 一.系统介绍 二.功能展示 1.用户登陆 2.好友列表 3.好友聊天 4.服务器日志 三.系统实现 四.其它 1.其他系统实现 2.获取源码 一.系统介 ...

  3. flutter offset_Flutter 仿微信界面聊天室 | 基于 (Flutter+Dart) 聊天实例

    1.项目介绍 Flutter是目前比较流行的跨平台开发技术,凭借其出色的性能获得很多前端技术爱好者的关注,比如阿里闲鱼,美团,腾讯等大公司都在投入相关案例生产使用.flutter_chatroom项目 ...

  4. 高仿QQ即时聊天软件开发系列之三登录窗口用户选择下拉框

    上一篇高仿QQ即时聊天软件开发系列之二登录窗口界面写了一个大概的布局和原理 这一篇详细说下拉框的实现原理 先上最终效果图 一开始其实只是想给下拉框加一个placeholder效果,让下拉框在未选择未输 ...

  5. 卸载nginx php mysql_centos7中配置nginx+php-fpm+swoole+mysql环境教程

    centos7在数据中心服务器中使用较为广泛,为了方便用户配置环境,本文介绍了在centos7系统下部署nginx+php-fpm+swoole+mysql环境的详细步骤. 一.运行nginx 1.新 ...

  6. android标题栏不被顶上去,Android仿微信QQ聊天顶起输入法不顶起标题栏的问题

    在这记录一下输入法弹出的一系列问题,有的输入法弹出就把整个布局弹上去,有的输入法弹出布局不会有变化,有的输入法弹出遮盖输入框等等问题,网上也有很多说加着加那的,但是看一下都不是很完整,解决不了所有问题 ...

  7. flutter图片聊天泡泡_flutter即时聊天IM仿微信|flutter聊天界面

    鉴于Flutter最近比较火,今天给大家分享的是基于flutter+dart全家桶技术开发的仿微信界面聊天FlutterChat项目实例.实现了消息+表情.图片预览.红包.长按菜单.视频/仿朋友圈等功 ...

  8. java实现仿微信app聊天功能_Android仿微信语音聊天功能

    本文实例讲述了Android仿微信语音聊天功能代码.分享给大家供大家参考.具体如下: 项目效果如下: 具体代码如下: AudioManager.java package com.xuliugen.we ...

  9. 2012年度最佳分享:仿webQQ界面,详情请下载,不吃亏

    原文:2012年度最佳分享:仿webQQ界面,详情请下载,不吃亏 源代码下载地址:http://www.zuidaima.com/share/1550463288052736.htm 2012年度最佳 ...

最新文章

  1. 计算机行业可以开安装服务费,安装服务费税率是多少
  2. IT认证不归路、CCIE高失业率
  3. mybatis3.2.8 与 hibernate4.3.6 混用
  4. Ubuntu18.04安装百度网盘
  5. PO增强,明细动抬头动
  6. SAP Spartacus HTTP请求的错误处理机制
  7. 闲谈.NET中的类型和访问修饰符
  8. C语言扫雷游戏简单实现
  9. QWaiteCondition思考3
  10. 【渝粤教育】国家开放大学2019年春季 1062文学英语赏析 参考试题
  11. (JAVA)Arrays数组工具类
  12. 深度学习auc_机器学习集成学习与模型融合!
  13. mysql 优化的一些小窍门
  14. pytorch 实现 LSTM AutoEncoder 与案例
  15. 70进货卖100利润是多少_进货价8块的产品,在网上卖100块,这个电商卖家能赚多少!...
  16. 爆竹声中一岁除,春风送暖入屠苏
  17. Unity中的Time
  18. java如何实现英文翻译中文,22年最新
  19. pr剪辑打开多个项目_Pr入门之十一:基本图形面板
  20. 期货开户公司想恶意滑点是做不到的

热门文章

  1. 自动发贴机(C# ``其实是山寨(- -!))
  2. BUUCTF 还原大师
  3. java面向对象 程序设计题_java面向对象程序设计练习题
  4. 《基于LSTM神经网络的双色球蓝球数字预测》
  5. 2021-07-21实用型OEM信息修改
  6. Unity3D---快捷键
  7. 进攻方向的选择(博弈论的诡计)
  8. 2020速卖通入驻条件以及费用现在来做速卖通晚不晚?速卖通还好做吗?
  9. 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第n个月的兔子对数为多少?
  10. 2月第二周安全要闻回顾:微软发通缉令 IBM关注犯罪