# IM-demo **Repository Path**: cloudsoftware_admin/IM-demo ## Basic Information - **Project Name**: IM-demo - **Description**: 登录、注册、发送消息、添加好友、离线消息 - **Primary Language**: PHP - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2019-12-09 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README **IM-DEMO** ==== 即时通讯demo;主要功能:登录、注册、发送消息、添加好友、离线消息 环境 ---- Ubuntu 16.04 Redis 4.0.8 Laravel 5.6 Swoole 2.1.0 Beanstalkd 1.1.0 MySQL 5.7.21 目录结构 -- im-demo : 前台页面 im-demo/js/config.js ```javascript //laravel-server地址 var api_host = 'http://localhost:8001'; //websocket服务地址 var websocket_host = 'ws://localhost:1024'; ``` laravel-server : 主要提供接口,nginx配置根目录为public swoole-server : websocket服务,用于转发消息 swoole-server/server.php ```php //启动websocket服务,监听所有地址的1024端口 $server = new swoole_websocket_server("0.0.0.0", 1024); //连接redis服务 $redis->connect('127.0.0.1', 6379); ``` 安装配置 ----- 1.配置laravel-server/public为nginx的根目录,并将config.js中的api_host修改为当前地址 2.在laravel-server目录下执行数据迁移语句 ```bash php artisan migrate ``` 3.启动队列消费进程 ```bash php artisan queue:work ``` 4.切换到swoole-server目录,启动websocket服务,并修改config.js中的websocket_host为服务地址 ```bash php server.php start ``` 逻辑 ------- 登录:im-demo登录成功后连接websocket服务器时,会返回消息类型为login的消息, 内容包括client_id,再将client_id与token发送到laravel-server绑定. 发送消息:im-demo发送消息到laravel-server,laravel-server处理逻辑与验证, 后将消息加入队列中. 消息队列:当im-demo请求laravel-server时,laravel-server并没有直接将消息转发,而是将消息加入到beanstalkd队列中,另有进程处理这些消息. laravel-server/app/Jobs/sendMessage.php ```php public function __construct(Users $from_user, Users $to_user, Messages $message) { $this->message = $message; $this->to_user = $to_user; $this->from_user = $from_user; $this->client = new Client('ws://127.0.0.1:1024'); } /** * Execute the job. * * @return void */ public function handle() { try{ $this->client->send(json_encode([ 'type'=>'send_to_friend', 'friend_id'=>$this->to_user->id, 'msg'=>$this->message->content, 'from'=>$this->from_user->user_name ])); $this->client->close(); $this->message->status = '1'; $this->message->save(); } catch (\Exception $exception) { } } ``` 离线消息:每次用户登录,都会查询是有未发送的消息,如果有则会加入队列中. laravel-server/app/Jobs/sendOfflineMessage.php ```php public function __construct($user_id) { $this->user_id = $user_id; $this->client = new Client('ws://127.0.0.1:1024'); } /** * Execute the job. * * @return void */ public function handle() { try{ $message = new Messages(); $user = new Users(); $msg_list = $message->where(['to'=>$this->user_id,'status'=>'0'])->get(); foreach ($msg_list as $k=>$v) { $this->client->send(json_encode([ 'type'=>'send_to_friend', 'friend_id'=>$v->to, 'msg'=>$v->content, 'from'=>$user->find($v->from)->value('user_name') ])); $v->status = '1'; $v->save(); } $this->client->close(); } catch (\Exception $exception) { } } ``` 接收消息:当swoole-server接收到类型sent_to_frined的消息时,从redis中获取接收用户的client_id,并将消息发送到该client_id.