今天,主要做了IM即时通讯功能中,用户登陆后,将cookie传递过来的用户信息,发送给wokerman服务器,然后操作redis保存。
一、将用户信息传给workerman简单实现
基本思路就是:通过引入jquery.cookie.js,获取用户登陆后的cookie,建立ws长连接,在客户端js操作,当连接打开时,将cookie发给workerman服务器,服务器处理信息,首先要给每个客户端添加序号,然后解密用户信息。
实例
//当客户端同服务器建立长连接时分配给客户整数序号 $ws_worker->onConnect = function ($connection) { global $global_uid; $connection->uid = ++$global_uid; }; // 当收到客户端发来的数据后返回hello $data给客户端 $ws_worker->onMessage = function($connection, $data) { //解密cookie $aes = new AES(); $user_josn = $aes->decrypt($data); $user_info = json_decode($user_josn, true); print_r($user_info); }; //当连接关闭时 $ws_worker->onClose = function($connection) { echo "connection closed\n"; };
运行实例 »
点击 "运行实例" 按钮查看在线实例
二、安装redis插件
下载redis插件 http://pecl.php.net/package/redis/2.2.3
移动到目标文件夹下 /Applications/MAMP/bin/php/php5.4.45/include/php/redis
cd到php文件夹,输入
./configure
如果产生一下错误的话
PHP ConfigureError: Please specify the install prefixoficonvwith–with-iconv=
那就使用此命令
然后
cd redis
/Applications/MAMP/bin/php/php5.4.45/bin/phpize
./configure --with-php-config=/Applications/MAMP/bin/php/php5.4.45/bin/php-config
make
make install
编译成功后,我们就需要吧so文件复制到MAMP中
sudo cp -p modules/redis.so /Applications/MAMP/bin/php/php5.4.45/lib/php/extensions/no-debug-non-zts-20100525
然后修改php的ini配置文件
在最后或者在Extensions的地方,加上一句
extension=redis.so
三、php操作redis,优化之前代码
前台在index.php页面js发送信息,这里新建一个空对象,然后把信息类型type,用户信息user,放在对象里,转成json格式,传给后台。后台三个事件 onConnect onMessage onClose 分别对应三个命名函数handle_connection handle_message handle_close。
实例
//建立连接 function handle_connection ($connection) { global $global_uid; $connection->uid = ++$global_uid; } //服务器收到客户端消息时 function handle_message ($connection, $data) { global $chat; $data = json_decode($data, true); $chat->process_msg($data); $chat->connection($connection); } //连接断开 function handle_close () { echo "connection closed\n"; }
运行实例 »
点击 "运行实例" 按钮查看在线实例
建立Chat类专门处理消息,然后建connection方法建立websoket process_msg处理各类消息,process_login
专门处理登陆信息,将需要初始化的操作放在构造函数里。构造函数里,包括AES解密类,redis插件加载及连接,序列号初始化,redis哈希表的key
连接的序列号作为哈希表的field,需要强调下,通过类外的handle_connection方法,在建立连接时通过自增序列号赋值给$connection的自定义属性uid,由于是长连接,那么在连接不断开的情况下$connection就一直存在,相当于全局变量,那么赋给他的自定义属性uid就一直存在,通过类内的connection方法将该对象传递给类内,然后在收到消息是,执行该方法,就作为类内的属性,然后就可以在类内用了
实例
//消息处理类 class Chat{ public function __construct () { $this->aes = new AES(); $this->redis = new Redis(); $this->redis->connect('127.0.0.1', 6379); $this->ws_uid = 0; $this->hash_wsuid_user_key = 'chater_user_list'; $this->connection = ''; } //建立websoket连接 public function connection ($connection) { $this->connection = $connection; } //处理消息 public function process_msg ($data) { if ($data['type'] == 'login') { $this->process_login($data['msg']); } } //处理登陆的信息 private function process_login ($data) { $user_json = $this->aes->decrypt($data); $user_info = json_decode($user_json, true); if ($user_info['uid'] <= 0) { return; } $this->redis->hSet($this->hash_wsuid_user_key, $this->connection->uid, $user_json); } }
运行实例 »
点击 "运行实例" 按钮查看在线实例
四、总结
redis插件很费劲,但是通过不断的查阅资料和反复的实验成功了,需要耐心
课程上业务实际上简单,但是实现过程,需要通过对象化来实现,具体来说,处理消息在类外用一个方法,具体逻辑通过建立类,然后类内的方法来实现,这个类主要是判断消息的type,如果是登陆类信息就交给专门的业务处理方法,然后在业务类里专门处理业务,这样整个代码就很对象化,逻辑严谨,代码简洁。