基于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 ‘0‘ COMMENT ‘接收用户id‘,
  `fid` int(11) NOT NULL DEFAULT ‘0‘ 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 ‘0‘ COMMENT ‘用户id‘,
  `fd` int(11) NOT NULL DEFAULT ‘0‘ 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>
    <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:然后没有标记已读的消息,就是新消息提醒。

原网址:https://www.cnblogs.com/zenghansen/p/5084738.html

原文地址:https://www.cnblogs.com/Json159/p/11291657.html

时间: 2024-10-16 19:34:47

基于swoole的网页一对一实时聊天的相关文章

基于swoole+Redis的消息实时推送通知

swoole+Redis将实时数据的推送 一 实现功能 设计师订单如果设计师未抢单,超时(5分钟)设计订单时时给设计师派送, 设计师公众号中收到派单信息 设计发布者收到派单成功信息 环境 centos6.10 redis-4.0.2 swoole-src-4.4.12 php-7.1.5 MYsyql5.7 在centos6默认是gcc-4.7,安装swoole的时候需要升级到gcc-4.8 二 实现流程 1.开启swoole server端监听 2.开启swoole client连接执行定时执

Python项目实战教程:web实时聊天室项目

新课强力来袭:基于Node.js的web实时聊天室项目! 麦子学院新课以马踏飞燕般的速度生粗来啦(*^__^*) .小伙伴们你萌确定不来一发吗? 啦啦啦--上图镇楼↓↓↓ 那些神奇的传送门→_→ 本课程:http://www.maiziedu.com/course/others/597-8698/ 李大大主页:http://www.maiziedu.com/group/common/course/59404/ 这里是正儿八经的课程介绍(快看快看o( ̄ヘ ̄o#)): 网站实时通讯一体化解决方案,采

基于百度云推送的高仿微信实时聊天Android源码

基于百度云推送的高仿微信实时聊天Android源码 使用服务:百度云推送    功能分类:社交     支持平台:Android 运行环境:Android       开发语言:Java     开发工具:Eclipse 下载地址:http://sina.lt/z84 源码简介 基于百度云推送的一款Android高仿微信的实时聊天app 运行动态图

基于flask的网页聊天室(二)

基于flask的网页聊天室(二) 前言 接上一次的内容继续完善,今天完成的内容不是很多,只是简单的用户注册登录,内容具体如下 具体内容 这次要加入与数据哭交互的操作,所以首先要建立相关表结构,这里使用flask-sqlalchemy来辅助创建 首先修改之前的init文件为: from flask import Flask from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() from web_chatroom.models impor

基于comet服务器推送技术(web实时聊天)

http://www.cnblogs.com/zengqinglei/archive/2013/03/31/2991189.html Comet 也称反向 Ajax 或服务器端推技术.其思想很简单:将数据直接从服务器推到浏览器,而不必等到浏览器请求数据. 主要思想:服务器端将数据推送到客户端(浏览器) 本人做了简单的web实时聊天系统:服务器推送(聊天).zip 系统简单说明如下: { 系统所用数据库:sqlite数据库 UserInfo:用户信息表 UserRelation:用户关系表 Mes

基于WebSocket实现网页版聊天室

WebSocket ,HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议,其使用简单,应用场景也广泛,不同开发语言都用种类繁多的实现,仅Java体系中,Tomcat,Jetty,Spring等都提供了对WS的API支持.本篇不做理论探究,仅自娱自乐,简单实现网页版的聊天室功能,在实际开发场景中变通使用即可.废话不叽歪,直接撸出来—— 1  简单页面 <!DOCTYPE html> <html lang="en"> <head> &l

php只能做网站?基于swoole+websocket开发双向通信应用

前言 众所周知,PHP用于开发基于HTTP协议的网站应用非常便捷.而HTTP协议是一种单向的通信协议,只能接收客户端的请求,然后响应请求,不能主动向客户端推送信息.因此,一些实时性要求比较高的应用,如实时聊天.直播应用.在线网页游戏等,就不适合采用HTTP协议.即使采用客户端主动轮询的方式来间接实现双向通信,也会较大地增加服务器的负担,增大代码的复杂性,不利于维护. 那么,是否PHP就无法用来开发双向通信的应用呢? 答案是否定的.PHP内置socket通信支持,可以与linux程序基于socke

jQuery实时聊天jquery-chat

jquery-chat是基于jQuery UI + Node.js + Socket.IO 实现100%纯JavaScript实时聊天(客户端和服务器都是JS),实现了facebook / Gmail风格的网页聊天. 快速使用Romanysoft LAB的技术实现 HTML 开发Mac OS App,并销售到苹果应用商店中. <HTML开发Mac OS App 视频教程> 土豆网同步更新:http://www.tudou.com/plcover/VHNh6ZopQ4E/ 百度网盘同步:http

基于Server-Sent Event的简单在线聊天室

一.Web即时通信 所谓Web即时通信,就是说我们可以通过一种机制在网页上立即通知用户一件事情的发生,是不需要用户刷新网页的.Web即时通信的用途有很多,比如实时聊天,即时推送等.如当我们在登陆浏览知乎时如果有人回答了我们的问题,知乎就会即时提醒我们,再比如现在电子商务的在线客服功能.这些能大大提高用户体验的功能都是基于Web即时通信实现的. 普通HTTP流程 客户端从服务器端请求网页 服务器作出相应的反应 服务器返回相应到客户端 而由于HTTP请求是无状态的,也就是说每次请求完成后,HTTP链