基于swoole的网页一对一实时聊天
需求分析
网站上实现一对一即时沟通,能查看聊天记录以及离线留言,新消息提醒。
核心技术
html5的websocket,php的swoole扩展http://wiki.swoole.com/
数据表
- CREATE TABLE `msg` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `content` varchar(255) NOT NULL DEFAULT '' COMMENT '内容',
- `tid` int(11) NOT NULL DEFAULT '' COMMENT '接收用户id',
- `fid` int(11) NOT NULL DEFAULT '' COMMENT '发送用户id',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8 COMMENT='消息表';
- CREATE TABLE `fd` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `uid` int(11) NOT NULL DEFAULT '' COMMENT '用户id',
- `fd` int(11) NOT NULL DEFAULT '' COMMENT '绑定id',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='用户绑定表';
Server端代码
- <?php
- class Server
- {
- private $serv;
- private $conn = null;
- private static $fd = null;
- public function __construct()
- {
- $this->initDb();
- $this->serv = new swoole_websocket_server("0.0.0.0", 9502);
- $this->serv->set(array(
- 'worker_num' => 8,
- 'daemonize' => false,
- 'max_request' => 10000,
- 'dispatch_mode' => 2,
- 'debug_mode' => 1
- ));
- $this->serv->on('Open', array($this, 'onOpen'));
- $this->serv->on('Message', array($this, 'onMessage'));
- $this->serv->on('Close', array($this, 'onClose'));
- $this->serv->start();
- }
- function onOpen($server, $req)
- {
- // $server->push($req->fd, json_encode(33));
- }
- public function onMessage($server, $frame)
- {
- //$server->push($frame->fd, json_encode(["hello", "world"]));
- $pData = json_decode($frame->data);
- $data = array();
- if (isset($pData->content)) {
- $tfd = $this->getFd($pData->tid); //获取绑定的fd
- $data = $this->add($pData->fid, $pData->tid, $pData->content); //保存消息
- $server->push($tfd, json_encode($data)); //推送到接收者
- } else {
- $this->unBind(null,$pData->fid); //首次接入,清除绑定数据
- if ($this->bind($pData->fid, $frame->fd)) { //绑定fd
- $data = $this->loadHistory($pData->fid, $pData->tid); //加载历史记录
- } else {
- $data = array("content" => "无法绑定fd");
- }
- }
- $server->push($frame->fd, json_encode($data)); //推送到发送者
- }
- public function onClose($server, $fd)
- {
- $this->unBind($fd);
- echo "connection close: " . $fd;
- }
- /*******************/
- function initDb()
- {
- $conn = mysqli_connect("192.168.1.122", "root", "a123456");
- if (!$conn) {
- die('Could not connect: ' . mysql_error());
- } else {
- mysqli_select_db($conn, "test");
- }
- $this->conn = $conn;
- }
- public function add($fid, $tid, $content)
- {
- $sql = "insert into msg (fid,tid,content) values ($fid,$tid,'$content')";
- if ($this->conn->query($sql)) {
- $id = $this->conn->insert_id;
- $data = $this->loadHistory($fid, $tid, $id);
- return $data;
- }
- }
- public function bind($uid, $fd)
- {
- $sql = "insert into fd (uid,fd) values ($uid,$fd)";
- if ($this->conn->query($sql)) {
- return true;
- }
- }
- public function getFd($uid)
- {
- $sql = "select * from fd where uid=$uid limit 1";
- $row = "";
- if ($query = $this->conn->query($sql)) {
- $data = mysqli_fetch_assoc($query);
- $row = $data['fd'];
- }
- return $row;
- }
- public function unBind($fd, $uid = null)
- {
- if ($uid) {
- $sql = "delete from fd where uid=$uid";
- } else {
- $sql = "delete from fd where fd=$fd";
- }
- if ($this->conn->query($sql)) {
- return true;
- }
- }
- public function loadHistory($fid, $tid, $id = null)
- {
- $and = $id ? " and id=$id" : '';
- $sql = "select * from msg where ((fid=$fid and tid = $tid) or (tid=$fid and fid = $tid))" . $and;
- $data = [];
- if ($query = $this->conn->query($sql)) {
- while ($row = mysqli_fetch_assoc($query)) {
- $data[] = $row;
- }
- }
- return $data;
- }
- }
- // 启动服务器
- $server = new Server();
备注:swoole_websocket_server是基于tcp的长连接,仅支持cli模式运行。
启动服务器
- php Server.php
客户端代码
- <!DOCTYPE html>
- <html>
- <head>
- <title></title>
- <meta charset="UTF-8">
- <script src="jquery-2.1.1.min.js"></script>
- <script src="jquery.json.js"></script> /*js地址:https://files.cnblogs.com/files/zenghansen/jquery.json-2.3.min.js*/
- <script type="text/javascript">
- var fid = 1; //发送者uid
- var tid = 2; //接收者uid
- var exampleSocket = new WebSocket("ws://192.168.1.17:9502");
- $(function () {
- exampleSocket.onopen = function (event) {
- console.log(event.data);
- initData(); //加载历史记录
- };
- exampleSocket.onmessage = function (event) {
- console.log(event.data);
- loadData($.parseJSON(event.data)); //导入消息记录,加载新的消息
- }
- })
- function sendMsg() {
- var pData = {
- content: document.getElementById('content').value,
- fid: fid,
- tid: tid,
- }
- if(pData.content == ''){
- alert("消息不能为空");
- return;
- }
- exampleSocket.send($.toJSON(pData)); //发送消息
- }
- function initData() {
- var pData = {
- fid: fid,
- tid: tid,
- }
- exampleSocket.send($.toJSON(pData)); //获取消息记录,绑定fd
- }
- function loadData(data) {
- for (var i = 0; i < data.length; i++) {
- var html = '<p>' + data[i].fid + '>' + data[i].tid + ':' + data[i].content + '</p>';
- $("#history").append(html);
- }
- }
- </script>
- </head>
- <body>
- <div id="history" style="border: 1px solid #ccc; width: 100px; height: auto">
- </div>
- <input type="text" id="content">
- <button onclick="sendMsg()">发送</button>
- </body>
- </html>
ps1:再复制一份客户端,修改一下发送者你接收者的uid,即可进行模拟实时聊天。
ps2:此代码已经实现了加载历史记录的功能
ps3:若要增加新消息提醒功能,msg还需增加一个已读标示,然后推送给接收者的时候
- if($server->push($tfd, json_encode($data))){
- //标记已读
- }
ps4:然后没有标记已读的消息,就是新消息提醒。
如有疑问请加作者qq:375161864
基于swoole的网页一对一实时聊天的更多相关文章
- Java进阶:基于TCP通信的网络实时聊天室
目录 开门见山 一.数据结构Map 二.保证线程安全 三.群聊核心方法 四.聊天室具体设计 0.用户登录服务器 1.查看当前上线用户 2.群聊 3.私信 4.退出当前聊天状态 5.离线 6.查看帮助 ...
- 基于swoole+Redis的消息实时推送通知
swoole+Redis将实时数据的推送 一 实现功能 设计师订单如果设计师未抢单,超时(5分钟)设计订单时时给设计师派送, 设计师公众号中收到派单信息 设计发布者收到派单成功信息 环境 centos ...
- 基于Android Classic Bluetooth的蓝牙聊天软件
代码地址如下:http://www.demodashi.com/demo/12133.html BluetoothChat 基于Android Classic Bluetooth的蓝牙聊天软件,目前仅 ...
- 网页实时聊天之PHP实现websocket
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...
- 使用signalr实现网页和微信公众号实时聊天(上)
最近项目中需要实现客户在公众号中和客服(客服使用后台网站系统)进行实时聊天的功能.折腾了一段时间,实现了这个功能.现在将过程记录下,以便有相同需求的同行可以参考,也是自己做个总结.这篇是上,用手机编辑 ...
- 网页实时聊天之PHP如何实现websocket
网页实时聊天之PHP如何实现websocket 一.总结 一句话总结: 应用 PHP 的 socket 函数库:PHP 的 socket 函数库跟 C 语言的 socket 函数非常类似 PHP 实现 ...
- SignalR实现网页实时聊天功能
SignalR是利用html5 sokit方式实现网页的实时性,在客户端不支持html5的情况下通过轮询实现 实现原理是客户端发送的消息先去服务器,然后服务器根据需要将消息广播到需要接收信息的客户群. ...
- 网页实时聊天之js和jQuery实现ajax长轮询
众所周知,HTTP协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系.所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的长时间联系,从而源源不段地获取信息. 一直以来的方式 ...
- [转]网页实时聊天之js和jQuery实现ajax长轮询 PHP
网页实时聊天之js和jQuery实现ajax长轮询 众所周知,HTTP协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系.所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的 ...
随机推荐
- Flume内存溢出错误
java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:) at java.lang.Ab ...
- Python基础3- 变量与数字
1.Python变量不需要声明,其赋值操作既是变量声明和定义的过程;2.Python中每个变量在使用前都必须赋值,变量赋值后该变量才会被创建;3.Python变量是存储内存中的值,若变量赋值时内存中存 ...
- git 学习笔记3--status flow
1.status 通过执行 git status 命令,查看输出的信息来理解文件所处的状态以及可能的动作. 1.1 nothing to commit (working directory clean ...
- The StringFormat property
As we saw in the previous chapters, the way to manipulate the output of a binding before is shown is ...
- The 2015 China Collegiate Programming Contest D.Pick The Sticks hdu 5543
Pick The Sticks Time Limit: 15000/10000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others ...
- BZOJ3726 : PA2014Final Wykladzina
从上到下枚举下底边,维护$a[i]$表示$i$向上延伸多少距离里面没有坏点,$b[i]$表示$i$向上延伸多少距离里面最多只有1个坏点. 设$l0[i],r0[i]$表示以$a[i]$为最小值,往左往 ...
- Android中有关relativeLayout 和EditText的一些属性
http://www.cnblogs.com/jqyp/archive/2010/10/23/1859182.html RelativeLayout用到的一些重要的属性: 第一类:属性值为true ...
- hdu1019 Least Common Multiple
Problem Description The least common multiple (LCM) of a set of positive integers is the smallest po ...
- OSG中的HUD
OSG中的HUD 所谓HUD节点,说白了就是无论三维场景中的内容怎么改变,它都能在屏幕上固定位置显示的节点. 实现要点: 关闭光照,不受场景光照影响,所有内容以同一亮度显示 关闭深度测试 调整渲染顺序 ...
- 如何处理json字符转换为字典
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@?userName=%@&userPwd=%@& ...