在laravel-swoole和websocket入門(一)中,我們已經(jīng)就 擴(kuò)展的安裝和啟動(dòng)作了介紹, laravel-swoole除了能大幅度的提升系統(tǒng)性能之后,還有一個(gè)很大的功能是 websocket長鏈接,這篇將詳細(xì)介紹長鏈接部分。
1,啟動(dòng)長鏈接
- 首先我們要開放端口,比如我們要啟動(dòng)1215端口為長鏈接端口,那么服務(wù)器要先放行1215端口,具體放行的方法各種服務(wù)器不一樣,就不細(xì)說了。
- 修改 config/swoole_http.php 部分配置
'server' => [
//服務(wù)地址 用0.0.0.0代替127.0.0.1 具體原因不知,反正127.0.0.1連不上
'host' => env('SWOOLE_HTTP_HOST', '0.0.0.0'),
'port' => env('SWOOLE_HTTP_PORT', '1215'),
//是否后臺(tái)運(yùn)行,測試階段可以不用后臺(tái)運(yùn)行,方便查看運(yùn)行狀態(tài) 生產(chǎn)的時(shí)候后臺(tái)運(yùn)行
'daemonize' => env('SWOOLE_HTTP_DAEMONIZE', false),
]
'websocket' => [
//這里是 websocket的總開關(guān), true和falsefalse,看著辦
'enabled' => env('SWOOLE_HTTP_WEBSOCKET', true),
],
- 在路由文件里輸出下測試 route/websocket.php
Websocket::on('connect', function ($websocket, Request $request) {
echo "connect";
// called while socket on connect
});
Websocket::on('disconnect', function ($websocket) {
// called while socket on disconnect
echo "disconnect";
});
現(xiàn)在我們啟動(dòng)服務(wù),鏈接測試一下
php artisan swoole:http restart
客戶端可以使用這個(gè)網(wǎng)站來測試

微信截圖_20200616153724.png
在控制臺(tái)我們可以看到連接成功的提示

微信截圖_20200616154928.png
查看代碼
2,如何接收客戶端發(fā)送的信息,并在系統(tǒng)中進(jìn)行業(yè)務(wù)處理
建立一個(gè)長鏈接并不難,網(wǎng)上也有很多其他的方法,一個(gè)單文件腳本就可以建起長鏈接,但是我們很難在一個(gè)單文件里進(jìn)行復(fù)雜的業(yè)務(wù)處理。使用 swoole-websocket,我們可以很方便的把長鏈接發(fā)送的數(shù)據(jù)經(jīng)過路由轉(zhuǎn)到 Controller,就像處理正常的 http請(qǐng)求一樣,處理websocket, laravel里面的大部分功能都可以正常使用,如 Model,Cache等。可以和我們的業(yè)務(wù)邏輯高度契合。
- 首先我們約定所有的數(shù)據(jù)傳輸都是 json格式,必須包含兩個(gè)字段event,data。event就類似于請(qǐng)求的 route路由, data是請(qǐng)求的數(shù)據(jù)
{
"event": "login",
"data": {
"uid": 1
}
}
返回的數(shù)據(jù)也是類似
{
"event": "return",
"data": "我收到了你的消息{"uid":1}"
}
以下是大概思路,具體還請(qǐng)查看代碼
- 1,創(chuàng)建一個(gè)WebsocketHandler類,放在哪都行,我是放在了 app\Swoole
這個(gè)類主要是對(duì) websocket的一個(gè)操作類,有三個(gè)事件onOpen,onMessage,onClose,我這里只用了 onOpen事件,就是長鏈接建立鏈接事件,這里我要返回 fd(客戶端的一個(gè)編號(hào),后面所有向客戶端發(fā)信息都需要這個(gè) fd),當(dāng)然也可以做其他的處理
public function onOpen($fd, Request $request)
{
/**
* 客戶端建立起長鏈接后,返回客戶端fd
*/
$this->server->push($fd, json_encode(['event' => 'open', 'data' => ['fd' => $fd]]));
return true;
}
鏈接建立后客戶端會(huì)收到信息
{
"event": "open",
"data": {
"fd": 2
}
}
- 2,創(chuàng)建一個(gè)Parser類,仍然放在app\Swoole
這個(gè)類主要是對(duì)長鏈接傳送的數(shù)據(jù)進(jìn)行 encode和 decode,如果不想用 json或者有其他的數(shù)據(jù)轉(zhuǎn)換可以在這里面
public function encode(string $event, $data)
{
$string = ['event' => $event, 'data' => $data];
return json_encode($string);
}
public function decode($frame)
{
//這里是解析客戶端發(fā)來的數(shù)據(jù),我們約定所有的傳輸都是json
$json = $frame->data;
$data = json_decode($json, true);
if (!$data || !isset($data['event'])) {
return ['event' => 'error', 'data' => $frame->data];
}
return ['event' => $data['event'], 'data' => $data['data'] ?? ''];
}
- 3,創(chuàng)建一條路由,route/websocket.php
/**
* 定義一個(gè)login路由,指向控制器方法,和http類似
*/
Websocket::on('login','App\Http\Controllers\Index\LoginController@index');
- 4,修改 config/swoole_websocket.php config/swoole_websocket.php,設(shè)置我們剛才自已添加的兩個(gè)類
'handler' => \App\Swoole\WebsocketHandler::class,
'parser' => \App\Swoole\Parser::class,
- 5, 創(chuàng)建控制器方法App\Http\Controllers\Index\LoginController
public function index(Websocket $websocket, $data)
{
/**
* 這里就可以做業(yè)務(wù)處理,比如綁定用戶和fd等
*/
$websocket->emit('return', "我收到了你的消息" . json_encode($data));
}
這里面注入兩個(gè)變量,一個(gè)是 websocket,用來操作 websocket的,比如回復(fù)信息,data就是客戶端發(fā)送的數(shù)據(jù)
到此就可以測試了

微信截圖_20200616172054.png
查看代碼
有問題請(qǐng)留言
未完待續(xù)