• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

php swoole4 用WebSocket服务器搭建简易的点对点一对一的聊天功能进阶版

武飞扬头像
向宇it
帮助1

前言:
之前我写了一篇搭建简易的聊天室功能的文章,不知道的建议先去看一下: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后面,实际应用肯定会考虑更多,登录验证,信息安全,保存聊天记录进数据库等等。

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

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgekhkg
系列文章
更多 icon
同类精品
更多 icon
继续加载