PHP 微信小程序 WebSocket MySQL Redis实现聊天功能

本文介绍了如何使用MySQL实现离线消息存储,当用户不在线时接收消息,并在WebSocket配合下,一旦用户上线即可即时推送未读消息。同时,展示了如何通过Redis绑定用户与WebSocket连接,确保一对一的消息传递。
摘要由CSDN通过智能技术生成

1.Mysql 实现离线消息池。如果一个用户不在线,则其他用户发送给他的消息暂时存储在mysql。待该用户上线时,再从离线消息池取出发送。

2.Redis 实现每个连接websocket的服务都唯一绑定一个用户。通过用户账号 = fd 存到redis中。

微信小程序:

 

  

 websocket.php代码:

<?php
//创建WebSocket Server对象,监听0.0.0.0:9501端口
$ws = new Swoole\WebSocket\Server('0.0.0.0', 9501);

//连接Redis
$redis=new Redis();
$redis->connect('服务器地址',6379);

//连接MySQL
$con=mysqli_connect("服务器地址","数据库名称","数据库密码","数据表名称"); 

//监听WebSocket连接打开事件
$ws->on('Open', function ($ws, $request) {
    
});

//监听WebSocket消息事件
$ws->on('Message', function ($ws, $frame) use($redis) {
    
    $data=json_decode($frame->data,true);
    
    echo "{$frame->data}\n";
    print_r($data['me']);
    echo "\n";

    switch($data['type']){
        
        case 'open':
            echo "我:".$data['me'];
            echo "\n";

            //将登录者“我”的fd存入至Redis
            $redis->set($data['me'],$frame->fd);

            $me=$redis->get($data['me']);
            echo $me;
            echo "\n";
            
            //在数据库查询我离线时,别人给我发的消息
            $sql = "SELECT `me`,`content` from chats where `to` = '{$data['me']}' order by `add_time` asc";
            $result = mysqli_query($con,$sql);
            
            //如果有,展示出来,即把消息推给客户端,即推送给“我”
            if ($result) {
                $re = [];
                while($row = mysqli_fetch_assoc($result)) {
                    array_push($re, $row);
                }
                mysqli_free_result($result);
                foreach ($re as $v) {
                    $msg = [
                        'msg' => $v['content']
                    ];
                    $ws->push($frame->fd,json_encode($msg,true));
                }

                //推送给“我”之后,便将该消息删除处理
                $sql = "DELETE FROM chats where `to` = '{$data['me']}'";
                mysqli_query($con,$sql);
            }
            
            break;
            
        case 'chat':
            echo "给:".$data['to'];
            echo "\n";

            //从Redis中取出“当前好友”的fd
            $to=$redis->get($data['to']);

            echo "给的fd:".$to;
            echo "\n";            
            
            //所有在线的用户
            $fds = []; 
            foreach($ws->connections as $fd){
                array_push($fds, $fd);
            }

            //判断“我”的“当前好友”是否在线
            if (in_array($to,$fds)) {
                $msg = [
                    'msg' => $data['msg'],
                ];
                //如果在线,直接推送要发送的消息
                $ws->push($to,json_encode($msg,256));
            } else {
                //如果不在线,将要发送的消息存入至数据表
                $add_time = date('Y-m-d H:i:s');
                $sql = "INSERT INTO chats(`to`,`me`,`content`,`add_time`) values ('{$data['to']}','{$data['me']}','{$data['msg']}','{$add_time}')";
                mysqli_query($con,$sql);
            }
            
            break;
            
    }
});

//监听WebSocket连接关闭事件
$ws->on('Close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
});

$ws->start();

MySQL表字段:

运行效果:

用户11给用户a发消息,用户a不在线: 

 

先把消息放置MySQL离线消息池: 

 

 用户a一上线,就看到用户11发来的消息:

并且数据表中的离线消息被删除:

 

 都在线后就可以正常实时对话了:

另外,补充:简单实现两人3分钟未聊天服务端连接断开的功能:

首先,定义一个方法,用setTimeOut:

然后,在连接上服务端后和每次给服务端发送完一个消息后调用一下这个方法 :

 

一个使用Java实现的实时推送消息和保存消息的案例是基于Spring Boot和WebSocket技术的在线聊天应用程序。 下面是一个简单的示例代码,演示如何使用Java和Spring Boot创建实时聊天应用程序: 1. 创建WebSocket配置类 ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/chat").withSockJS(); } } ``` 2. 创建控制器类 ```java @Controller public class ChatController { @MessageMapping("/chat.sendMessage") @SendTo("/topic/public") public ChatMessage sendMessage(@Payload ChatMessage chatMessage) { return chatMessage; } } ``` 3. 创建消息实体类 ```java public class ChatMessage { private MessageType type; private String content; private String sender; private String time; // getters and setters public enum MessageType { CHAT, JOIN, LEAVE } } ``` 4. 创建前端页面 ```html <!DOCTYPE html> <html> <head> <title>WebSocket Chat</title> <script src="/webjars/jquery/jquery.min.js"></script> <script src="/webjars/sockjs-client/sockjs.min.js"></script> <script src="/webjars/stomp-websocket/stomp.min.js"></script> </head> <body> <div id="chat"> <div id="messages"></div> <form id="messageForm"> <input type="text" id="messageInput" /> <button type="submit">Send</button> </form> </div> <script type="text/javascript"> var stompClient = null; function connect() { var socket = new SockJS('/chat'); stompClient = Stomp.over(socket); stompClient.connect({}, function(frame) { console.log('Connected: ' + frame); stompClient.subscribe('/topic/public', function(message) { showMessage(JSON.parse(message.body)); }); }); } function showMessage(message) { var html = '<div class="message">'; html += '<span class="sender">' + message.sender + '</span>'; html += '<span class="time">' + message.time + '</span>'; html += '<p class="content">' + message.content + '</p>'; html += '</div>'; $('#messages').append(html); } $(function() { connect(); $('#messageForm').on('submit', function(event) { event.preventDefault(); var message = { type: 'CHAT', content: $('#messageInput').val(), sender: 'User', time: new Date().toISOString() }; stompClient.send("/app/chat.sendMessage", {}, JSON.stringify(message)); $('#messageInput').val(''); }); }); </script> </body> </html> ``` 通过上述代码,我们可以实现基于Java和Spring Boot的在线聊天应用程序。用户可以在前端页面上送消息,并立即在所有其他用户的页面上看到新消息。所有消息都将保存在后端数据库中,以便用户可以随时查看消息历史记录。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值