基于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协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系.所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的 ...
随机推荐
- Redis List命令
命令 解释 lpush key string 在key对应list的头部添加字符串元素,返回1表示成功,0表示key存在且不是list类型. rpush key string 同上,尾插入. ...
- BZOJ4546(原) : 三元组
设$f(x)=\sum_{x|d}p(d)$. 则$ans=\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n\mu(i)\mu(j)\mu(k)f(lcm(i,j))f(lcm ...
- JStorm之Nimbus简介
本文导读: ——JStorm之Nimbus简介 .简介 .系统框架与原理 .实现逻辑和代码剖析 )Nimbus启动 )Topology提交 )任务调度 )任务监控 .结束语 .参考文献 附:JStor ...
- hive :MetaException(message:Version information not found in metastore. )
MetaException(message:Version information not found in metastore. ) Hive now records the schema vers ...
- zookeeper清除日志文件工具
zookeeper运行时间长了以后,日志会成为一个比较大的问题.比如作者压力测试hbase一周以后,zookeeper日志文件达到了10G的规模.由于zookeeper日志文件不能随意删除,因为一个长 ...
- Hadoop IPC的代码结构分析
与IPC相关的代码在org.apache.hadoop.ipc包下.共七个文件,其中4个辅助类: RemoteException Status VersionedProtocol Connection ...
- Android开发之详解五大布局
http://bbs.chinaunix.net/thread-3654213-1-1.html 为了适应各式各样的界面风格,Android系统提供了5种布局,这5种布局分别是: LinearLayo ...
- InterBase数据库迁移到MySQL(数据导入)
在这个脚本中我使用的是Python的ORM框架SQLAlchemy来连接远程的MySQL数据库的,在写这个脚本的时候为了方便参数的输入,我就给之前和这个脚本添加了一个新的功能,就是在调用这个脚本的时候 ...
- [友盟微博分享]does not contain bitcode. You must rebuild it with
1.我的 Xcode 明明打开了 bitcode 了,为什么还会报错呢?挺奇怪的. 2.上网一查,才知道,友盟需要 bitcode,Xcode 不支持,只要关闭bitcode就可以 了. 3.其实我也 ...
- MySQL 服务无法启动。服务没有报告任何错误。
MySQL数据库在升级到5.7版本后,和之前的版本有些不一样,没有data文件夹,我们都知道MySQL数据库文件是保存在data文件夹中的,网上有人说把5.6版本的data文件夹拷贝一个,这种说法听听 ...