前言:大家好,我自己有一个项目完成度已经很高了,我自己的技术怎么说也不是太强,在完成这个项目中我学习很多知识,比如说使用swoole实现二维码登录,说实在的,我本身是一个前端,但是日常学习和工作中也会写一下php代码,swoole怎么说呢,也算是专业对口,在断断续续研究一个星期后,我也完成了app扫码登录的功能,怎么说,也算有个新技术傍身,到时候面试的时候还可以跟面试官吹吹牛。 首先呢先要介绍下我这个某某项目的要求和情况,因为毕竟有版权,我不会透露什么项目实际名称,实际上呢是这样的,这个项目分为安卓端(原生),ios端(原生),和网页端(vue),安卓和ios我不懂,这是别人完成的,我们这期的技术是使用swoole二维码登录,这当然是大部分网页端需要实现的功能,苦逼的我只能看了又看,做了又做了。 其实swoole的部署实际是后端接口api的事情,但是我们是一个小项目,php我也会弄,所以就兼职了一下,前面说了这么多,我们就不废话了,开始吧 什么是swoole,我其实不知道,因为用过php,我一直以为是php某个框架上的功能,我把扩展加上去就可以用了,比如laravel框架什么的,看了一个星期的,怎么说呢,其实不是这个样子,因为swoole其实是一个服务器,我们在实现代码后,swoole就会如同apache一样,你去访问请求这个地址,他会根据代码来输出数据,跟apache真的很像,而我们使用了他socket功能,先使用网页(就是请求)访问跟他这个swoole服务器建立连接后,我们会返回一个通道的id,这个id会通过二维码展示出来,然后手机去扫描这个二维码后,获得这个id,然后将手机登录时候获得token(登录验证唯一数据,需要安全保存)和这个id发送给这个swoole服务器连接通道(通过id来判断是哪个通道),通道收到请求后,会发送请求给网页,这个请求数据就包含token,然后网页把token保存起来,再跳转到主页,完成了登录,随后关闭swoole通道连接。
下面我通过代码来给大家解释
首先我们要给php加上swoole的扩展这个具体的请看我MAMP安装swoole记录,踩坑记录
1.新建swoole服务器
$this->server = new Swoole\WebSocket\Server("127.0.0.1", 9501);
2.监听swoole服务是否运行
$this->server->on('start', function ($server) { echo "Websocket Server is started at ws://127.0.0.1:9501\n"; });
3.swoole运行后,监听是否有人和swoole建立了连接,前端如果swoole建立了连接,相当于一个通道,他们之间就可以互相发送信息(1)前端建立与swoole连接后
swoole代码:
js代码前端连接swoole服务器的代码
function handShake() {
qrCodeData.status = 'start'
qrCodeData.errorInfo = '正在加载'
getLoginQrCodeUrl()
var wsServer = 'ws://127.0.0.1:9501';
var websocket = new WebSocket(wsServer);
//如果与服务器链接成功,则生成url二维码
websocket.onopen = function () {
qrCodeData.status = 'ready'
qrCodeData.errorInfo = '服务器连接成功'
websocket.send(JSON.stringify({ test: data.login }));
};
websocket.onclose = function () {
if (qrCodeData.status != 'error') {
qrCodeData.errorInfo = '二维码失效,请重新链接'
qrCodeData.status = 'close'
}
};
websocket.onmessage = function (evt) {
console.log('Retrieved data from server: ' + evt.data);
let userInfo = JSON.parse(evt.data)
store.dispatch('test/login', { ...userInfo }).then(() => {
router.push({ path: '/' })
websocket.close()
})
};
websocket.onerror = function (evt, e) {
console.log('Error occured: ' + evt.data);
console.log(e)
qrCodeData.status = 'error'
qrCodeData.errorInfo = '服务器连接错误,请查看网络连接'
};
}
4.完成前端代码连接大米 我们给php加上swoole的扩展,完成后 新建server文件夹后,在文件夹新建run.php的文件 然后写下以下代码
<?php
//创建一个对象Swoole_Lite的对象实例
$swooleLite = new Swoole_Lite();
//类声明Swoole_Lite,其中有个构造函数__construct,实例化的同时就会运行此函数,实际上就是把需要运行的函数都放在了__construct
class Swoole_Lite
{
public $server;
public $table;
public function __construct()
{
//实例化表格,参数 int : 最大行数
//$this->table实际上为了存储前端和swoole连接后的通道id
$this->table = new swoole_table(1024);
//设置表格字段 参数 (字段名:string , 字段类型:int、float、string , 长度:int)
$this->table->column('id',$this->table::TYPE_INT,11);
//创建表格
$this->table->create();
$this->server = new Swoole\WebSocket\Server("127.0.0.1", 9501);
//设置心跳检测60秒时间内没有数据,自动关闭
$this->server->set([
'heartbeat_check_interval' => 30,
'heartbeat_idle_time' => 60,
]);
$this->server->on('start', function ($server) {
echo "Websocket Server is started at ws://127.0.0.1:9501\n";
});
$this->server->on('open', function (Swoole\WebSocket\Server $server, $request) {
echo "server: handshake success with fd{$request->fd}\n";
});
$this->server->on('message', function (Swoole\WebSocket\Server $server, $frame) {
$data = json_decode($frame->data);
//判断是否有重复websocket链接,关闭它 通过login来判断
$this->disconnectRepeatWebSocket($data->login);
$this->table->set($data->login,['id'=>$frame->fd]);
// echo $table[$data->login];
// echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
// $server->push($frame->fd, "this is server");
});
$this->server->on('close', function ($ser, $fd) {
foreach ($this->table as $key => $value) {
if($value['id'] == $fd){
$this->table->del($key);
}
}
$ser->push($fd,'close');
});
$this->server->on('request', function ($request, $response) {
$result = array('ret'=>'404','data'=>array('err_code'=>'1','ip'=>$request->server['remote_addr']),'msg'=>'没有可用的连接');
$response->header('Content-Type', 'text/plain');
$response->header('Charset', 'utf-8');
var_dump($request->post);
foreach ($this->table as $key => $value) {
var_dump($key);
}
if ($this->server->isEstablished($this->table->get($request->post['login'],'id'))) {
$userInfo = json_encode($request->post);
$this->server->push($this->table->get($request->post['login'],'id'),$userInfo);
$result['ret'] = '200';
$result['data']['err_code'] = '0';
$result['msg'] = '发送登录信息成功';
}
$response->end(json_encode($result));
});
$this->server->start();
}
function disconnectRepeatWebSocket($login){
if($login){
if($this->table->exist($login)){
$this->server->isEstablished($table->get($login, 'id')) && $this->server->disconnect($table->get($login, 'id'));
$this->table->del($login);
}
}
}
// //发送用户数据给web端,实现登录
// function pushMessageToWeb($fd,$post_data){
// $this->server->push($fd,json_encode($post_data));
// }
}
这段代码我也是从网上找来的,其中改了点地方,时间很长了,我也记不住了改动了哪里,我说下我的理解吧,也请大家指正,
首先我们先启动swoole服务,
使用cmd或者终端输入 php /路径/server/run.php
如下图
这就表示swoole服务器启动成功了。这样就完成了二维码扫码的功能实现。
哈哈,肯定不能这样结束,我刚刚只是告诉大家怎么使用swoole,并且贴上了代码
下面我还要给大家介绍下二维码登录时怎么实现的,以及解读下前端和swoole还有后端的代码,那我们就开始吧。swoole的run.php的代码分析我就写上面代码块中,一步步地分析,大家可以看下上面的代码注释,