IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> php swoole4 用WebSocket服务器搭建一个简易的点对点一对一的聊天功能(进阶版) -> 正文阅读

[网络协议]php swoole4 用WebSocket服务器搭建一个简易的点对点一对一的聊天功能(进阶版)

前言:
之前我写了一篇搭建简易的聊天室功能的文章,不知道的建议先去看一下:https://blog.csdn.net/qq_36303853/article/details/119958945
这时候好学的小伙伴就会问了,那怎么实现一对一的聊天呢?

前提

注:这里的用的redis保存用户信息,你也可以用mysql数据库,我提供的只是思路,方法不唯一,能实现就行

  • 一台服务器
  • 安装swoole4
  • php>=7.2
  • 安装rerdis(我这里用的redis,你也可以用mysql数据库)
  • 宝塔和阿里云分别开放对应端口(我这里用的9502)
  • 一个域名(我这里是配置了ssl的,没有配置ssl的代码跟着改就可以了,别问我怎么改,之前的文章已经写了,不知道的回去看看吧)

代码实现

WS.php服务端代码

<?php
class WS{
    private $ws = null;
    private $redis = null;
    
    public function __construct(){
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
        //创建WebSocket Server对象,监听0.0.0.0:9502端口
        $this->ws = new Swoole\WebSocket\Server('0.0.0.0', 9502, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
        // $this->ws = new Swoole\WebSocket\Server('0.0.0.0', 9502);
        //配置ssl文件路径
        $this->ws->set([
            'ssl_cert_file' => '/www/server/panel/vhost/cert/114.55.29.146/fullchain.pem',     // worker process num
            'ssl_key_file' => '/www/server/panel/vhost/cert/114.55.29.146/privkey.pem',
            // 'task_worker_num' => 4//设置异步任务的工作进程数量
            'worker_num' => 4,
            'dispatch_mode' => 5,   //uid dispatch
        ]);

        //监听WebSocket连接打开事件
        $this->ws->on('Open', [$this, "onOpen"]);
        
        //监听WebSocket消息事件
        $this->ws->on('Message', [$this, "onMessage"]);
        
        //监听WebSocket连接关闭事件
       $this->ws->on('Close', [$this, "onClose"]);
       
        //启动服务器
       $this->ws->start();
    }
    
    public function onOpen($ws, $request){
        // var_dump($request->fd, $request->get['uid']);
        $info = [
            'fd' => $request->fd,
            'send_uid' => $request->get['send_uid'],
            'this_uid' => $request->get['this_uid'],
            'name' => $request->get['name']
        ];
        //保存用户信息进redis
        $this->redis->set($request->get['this_uid']."_uid", json_encode($info));
        // $ws->push($request->fd, "欢迎客户端: {$request->fd}\n");
    }
    
    public function onMessage($ws, $frame){
        $data = json_decode($frame->data, true);//获取前端传过来的数据
        $send_info = json_decode($this->redis->get($data['send_uid'] . '_uid'), true);//获取接收方数据
        $ws->push($frame->fd, json_encode($data));//发给自己
        $data['name'] = urldecode($data['name']);//中文编码问题
        if($send_info){
	        /*
	        如果 A 和 B 在一个页面聊天,C 又给 A 发了一条消息,这样 A 和 B 的聊天列表里面,
	        A 也会收到 C 发送的消息,因为 A 满足了'在线'的要求,
	        所以在前端接收消息那里需要判断推送给自己的消息
	        这样就知道只要你在聊天页面就能收到所有人的消息,就可以实现一个你在聊天的过程中,
	        顶部弹出一个提示框 【孙某人给您发了一条消息,请注意查收哦!】
	        */
        	$ws->push($send_info['fd'], json_encode($data));//发给接收方
        } 
    }
    
    public function onClose($ws, $fd){
        echo "客服端:{$fd} 关闭\n";
    }
    
}
new WS();

static/chat.html客户端代码

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>简易聊天室</title>
</head>
<div id="welcome"></div>
<input type="text" id="input"/>
<br />
<button type="buton" onclick="send()">发送</button>
<div id="message"></div>
<body>
</body>

<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
    var wsServer = 'wss://xiangyu.huangzhongxin.cn:9502' + window.location.search;
    var websocket = null;
    var lock = false;
    $(function(){
        relink();
    })
    
    function link(){
        websocket = new WebSocket(wsServer);
        websocket.onopen = function (res) {
            console.log(11)
            $("#welcome").html("<h1>连接成功!欢迎</h1>");
        };
        
        websocket.onclose = function (res) {
            // $("#message").append("<h3>连接关闭</h3>");
            websocket.close();
            relink();
        };
        
        websocket.onmessage = function (res) {
            var request =new UrlSearch();
            console.log(request,11);
            var info = JSON.parse(res.data);
            console.log(info,22);
            if(request['this_uid'] == JSON.parse(res.data)['this_uid']){
                $("#message").append("<h3>我说:" + info['message'] + "</h3>")
            }else if(request['this_uid'] == JSON.parse(res.data)['send_uid'] && request['send_uid'] == JSON.parse(res.data)['this_uid']){
                $("#message").append("<h3>" + info['name'] + "对你说:" + info['message'] + "</h3>")
            }
        };
        
        websocket.onerror = function (res) {
            // $("#message").append("<h3>" + res + "</h3>");
            websocket.close();
            relink();
        };
    }
    
    function send(){
        var request = new UrlSearch(); //实例化
        request['message'] = $('#input').val();
        console.log(JSON.stringify(request))
        websocket.send(JSON.stringify(request));
    }
    
    function UrlSearch() 
    {
       var name,value,res; 
       var str=location.href; //取得整个地址栏
       var num=str.indexOf("?") 
       str=str.substr(num+1); //取得所有参数   stringvar.substr(start [, length ]
    
       var arr=str.split("&"); //各个参数放到数组里
       for(var i=0;i < arr.length;i++){ 
            num=arr[i].indexOf("="); 
            if(num>0){ 
                name=arr[i].substring(0,num);
                value=arr[i].substr(num+1);
                this[name]=value;
            } 
        } 
    } 

    function relink(){
        if(lock){
            return false;
        }
        lock = true;
        setTimeout(function(){
            link();
            lock = false;
        }, 1000)
    }
</script>
</html>


启动

  1. 启动服务端
    在这里插入图片描述
    注:如果开启不了可能是9502端口被占用了,杀死即可

    netstat -anp  | grep  9502  	//查看端口号 9502
    

    在这里插入图片描述

    kill -9 4663  	//杀死进程
    
  2. 浏览器分别开启多个客户端窗口,进行聊天

     域名/static/chat.html?send_uid=1&this_uid=2&name=姓名
    

    在这里插入图片描述

结果

  • 可以看出,两个人可以正常进行聊天,而第三者无法插足。
  • 这里this_uid指当前用户uid,name指当前用户的姓名,send_uid指的是接受信息人的uid
  • 当然我这里只是为了好理解,将信息都拼接到url后面,实际应用肯定会考虑更多,登录验证,信息安全,保存聊天记录进数据库等等。

如果您觉得本篇对你有帮助,可以点关注,给个赞,支持一下,过程有遇到什么问题也欢迎评论私信,进行交流

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-09-03 12:18:17  更:2021-09-03 12:20:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:31:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码