laravel 中workman的應(yīng)用

由于自己寫了一個(gè)博客,一直對workman有想法的我邦尊,突發(fā)奇想的想在博客里面弄個(gè)聊天室,因此就研究了一下workman,看了下workman的手冊链峭,然后了解了一下又沾,workman,發(fā)現(xiàn)他是通過socket進(jìn)行通訊杖刷,由于socket是tcp層的,因此可以進(jìn)行長鏈接役听,接著雙向通訊不瓶,而不像php的普通情況蚊丐,通過http或者h(yuǎn)ttps進(jìn)行通訊艳吠,因?yàn)閔ttp或者h(yuǎn)ttps每次通訊需要三次握手,四次揮手凛篙,而且服務(wù)器始終是處于被動(dòng)狀態(tài)栏渺,無法主動(dòng)和客戶端進(jìn)行交流磕诊,因此若是客戶端不進(jìn)行輪詢的情況下,幾乎是做不到實(shí)時(shí)通訊滞磺。

而workman可以做到击困,workman是用PHP開發(fā)的广凸,他就是用來調(diào)用socket來進(jìn)行通訊的蛛枚。此外還需要補(bǔ)充一點(diǎn)就是蹦浦,workman他存在的一個(gè)缺陷企蹭,由于他本身是屬于單線程的谅摄,如果你的服務(wù)器是多線程的,那workman是始終無法占滿cpu的顽照,所以對于多線程的服務(wù)器來說闽寡,workman的工作效率的偏低的爷狈,因此考慮到多線程的問題,設(shè)計(jì)workman的大佬們思币,又設(shè)計(jì)了一款workman的升級(jí)版羡微,gateway妈倔,它是屬于多線程的,如果用戶量大的話毅哗,只要CPU處理的過來,他就完全能繼續(xù)扛著随夸,其實(shí)gateway的設(shè)計(jì)原理就是:你有幾個(gè)線程,我就開幾個(gè)work滿。

廢話不多說酥艳,接著開始說workman.

下載和安裝workman就不說了充石,直接說如何使用吧霞玄。

由于workman的啟動(dòng)是需要命令框的坷剧,因此在laravel中,有專門用來生成自定義命令框的一個(gè)模塊撕瞧,commond狞尔,具體的話偏序,可以去laravel中查看。

php artisan make:command? WorkermanCommand? (創(chuàng)建自己的 laravel Artisan Console);

接著就在handle()方法中寫上寇漫,你的命令邏輯。


命令邏輯


自定義的命令邏輯

我自己定義的命令邏輯是 wk? {action}? :action 就是你要執(zhí)行的方法逸月。

例如碗硬,我需要執(zhí)行start ,就可以寫成: php artisan wk start

從handle()方法中看到瓢颅,當(dāng)action為start 的時(shí)候挽懦,調(diào)用chat_room()這個(gè)方法。

chat_room方法()

可以看到執(zhí)行的邏輯就是:

1.先實(shí)例化workman.

2.開啟1個(gè)進(jìn)程醒第,至于為什么不開啟多個(gè)進(jìn)程进鸠,那是因?yàn)榭湍辏?dāng)開啟多個(gè)進(jìn)程以后,如果在不同進(jìn)程中司恳,用戶和用戶之間是不能通訊得榔至,因此就只開一個(gè)進(jìn)程就ok了唧取,如果無法理解,就舉個(gè)例子邢享,現(xiàn)在有4個(gè)房間骇塘,然后一堆人站在房間前面韩容,每一個(gè)人只能隨機(jī)選擇一個(gè)房間進(jìn)入群凶,當(dāng)他們進(jìn)入房間后,同一個(gè)房間的人能相互交流赠尾,不同房間的人只能干瞪眼毅弧,沒法交流够坐。(這就是為什么開一個(gè)進(jìn)程的原因)

3.設(shè)置一個(gè)變量崖面,用來存放用戶信息嘶朱。以便于對用戶進(jìn)行通訊發(fā)送消息光酣。

4.當(dāng)用戶連接的時(shí)候救军,發(fā)送信息的時(shí)候唱遭,這時(shí)候獲取到用戶的信息,并且將他存放到定義好的變量中疫鹊,然后將他發(fā)送的信息遍歷給其他的每個(gè)一用戶司致,做到信息的實(shí)時(shí)通訊脂矫。

5.當(dāng)用戶斷開連接的時(shí)候庭再,為了減少workman推送消息的資源,首先吧斷開連接的用戶給剔除了颅围,然后廣播通知其他用戶恨搓,該用戶已經(jīng)退出聊天奶卓。

6.設(shè)置一個(gè)心跳夺姑,看了官方文檔掌猛,主要作用就是為了防止長鏈接長時(shí)間不通訊導(dǎo)致被路由節(jié)點(diǎn)強(qiáng)制斷開,說白了就是需要定期的和路由節(jié)點(diǎn)說一聲:兄弟竹海,我和他還活著丐黄,別我們T了灌闺。 他這邊的心跳功能,就是一個(gè)定時(shí)器甩卓,客戶端長時(shí)間不發(fā)信息給服務(wù)器逾柿,但是服務(wù)器又怕被斷開宅此,咋辦呢诽凌,那服務(wù)器只能侣诵,定時(shí)的給客戶端發(fā)個(gè)消息。這樣就能保持不被斷開了财搁。心跳間隔建議值:建議客戶端發(fā)送心跳間隔小于60秒躬络,比如55秒穷当。(這是官方建議馁菜,我設(shè)置了59秒)

這就是PHP這塊的代碼。

在cmd命令框執(zhí)行:php artisan wk start? ? ? ? ? ? ? ---這樣workman 就啟動(dòng)了峭火。

下面貼一下前端的js代碼卖丸。


html

這塊是html.就是一個(gè)聊天框.


js代碼

前端需要處理的很少稍浆,只需要發(fā)送信息和接受消息粹湃。

下面看一下恐仑,成果


這是模擬的兩個(gè)用戶的測試結(jié)果。

當(dāng)然你也可以到www.youngxs.com/boke/boke_chat來測試玩一下为鳄。一個(gè)瀏覽器同時(shí)開兩個(gè)就可以了裳仆。

有不懂的可以咨詢我:601902897? 歡迎來騷擾

下面就是貼下代碼:

<?php

namespace App\Console\Commands;

use Workerman\Worker;

use \Workerman\Lib\Timer;

use Illuminate\Console\Command;

class WorkermanCommand extends Command{

? ? private $server;

? ? /**

* The name and signature of the console command.

*

? ? * @var string

*/

? ? protected $signature = 'wk {action}';

? ? /**

* The console command description.

*

? ? * @var string

*/

? ? protected $description = 'Start a Workerman server.';

? ? /**

* Create a new command instance.

*

? ? * @return void

*/

? ? public function __construct()

{

? ? ? ? parent::__construct();

? ? }

? ? /**

* Execute the console command.

*

? ? * @return mixed

*/

? ? public function handle()

{

? ? ? ? global $argv;? //$argv 在ArgvInput類中被定義了,就是$_SERVER['argv'];

? ? ? ? $arg = $this->argument('action');

? ? ? ? $argv[1] = $argv[2];

? ? ? ? $argv[2] = isset($argv[3]) ? "-{$argv[3]}" : '';

? ? ? ? switch ($arg) {

? ? ? ? ? ? case 'start':

? ? ? ? ? ? ? ? $this->chat_room();

? ? ? ? ? ? ? ? break;

? ? ? ? }

}

? ? private function chat_room()

{

? ? ? ? //建立socket連接

? ? ? ? $http_worker = new Worker('websocket://0.0.0.0:2001');

? ? ? ? // 啟動(dòng)4個(gè)進(jìn)程對外提供服務(wù)

? ? ? ? $http_worker->count = 1;

? ? ? ? //定義一個(gè)屬性孤钦,用來存放用戶的連接信息歧斟,$connection

? ? ? ? $http_worker->uidConnections = array();

? ? ? ? //socket事件類中的,鏈接屬性偏形,調(diào)用閉包函數(shù)

? ? ? ? $http_worker->onConnect = function($connection)use($http_worker)

{

? ? ? ? ? ? // 設(shè)置連接的onMessage回調(diào)

? ? ? ? ? ? $connection->onMessage = function($connection, $data)use($http_worker)

{

? ? ? ? ? ? ? ? //獲取用戶傳輸過來的數(shù)據(jù),并且進(jìn)行json_decode解析

? ? ? ? ? ? ? ? $data=json_decode($data,true);

? ? ? ? ? ? ? ? //獲取用戶ID接著將用戶信息$connection俊扭,存儲(chǔ)在$http_worker->uidConnections中队橙,

? ? ? ? ? ? ? ? $http_worker->uidConnections[$data['id']]=$connection;

? ? ? ? ? ? ? ? //給其他用戶發(fā)送,該用戶發(fā)送的信息萨惑,為了保持?jǐn)?shù)據(jù)的實(shí)時(shí)性捐康。

? ? ? ? ? ? ? ? foreach ($http_worker->uidConnections as $k =>$v){

? ? ? ? ? ? ? ? ? ? if($k != $data['id']){

? ? ? ? ? ? ? ? ? ? ? ? if(isset($data['content'])){

? ? ? ? ? ? ? ? ? ? ? ? ? ? $v->send(json_encode(['status'=>0,'msg'=>$data['content']]));

? ? ? ? ? ? ? ? ? ? ? ? }

}

}

? ? ? ? ? ? };

? ? ? ? ? ? //設(shè)置用戶斷開連接的回調(diào)。

? ? ? ? ? ? $connection->onClose = function($connection)use($http_worker)

{

? ? ? ? ? ? ? ? foreach ($http_worker->uidConnections as $k=>$v){

? ? ? ? ? ? ? ? ? ? if($v==$connection){

? ? ? ? ? ? ? ? ? ? ? ? unset( $http_worker->uidConnections[$k]);

? ? ? ? ? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? ? ? ? ? $v->send(json_encode(['status'=>0,'msg'=>$k.'下線了']));

? ? ? ? ? ? ? ? ? ? }

}

? ? ? ? ? ? };

? ? ? ? ? ? /*設(shè)置心跳庸蔼,為防止長鏈接斷開? ? ? ? ? ? * 原理:就是設(shè)置一個(gè)定時(shí)器解总,定時(shí)的向客戶端發(fā)送數(shù)據(jù)? ? ? ? ? ? * $time_interval 時(shí)間間隔* */

? ? ? ? ? ? $time_interval = 59;

? ? ? ? ? ? Timer::add($time_interval, function()use($http_worker)

{

? ? ? ? ? ? ? ? if(count($http_worker->uidConnections)>0){

? ? ? ? ? ? ? ? ? ? foreach ($http_worker->uidConnections as $connection) {

? ? ? ? ? ? ? ? ? ? ? ? $connection->send(json_encode(['status'=>1,'smg'=>'socket_hot']));

? ? ? ? ? ? ? ? ? ? }

}

? ? ? ? ? ? });

? ? ? ? };

? ? ? ? Worker::runAll();

? ? }

}


下面的是JS代碼

? ? var id='youngxs_name'+ Date.parse(new Date());

? ? $('.italic').html('游客:'+id)

var url='ws://127.0.01:2001'

? ? var ws =new WebSocket(url);

? ? ws.onopen =function() {

var data={'id':id}

data=JSON.stringify(data);

? ? ? ? ws.send(data);

? ? ? ? $('#chat_sure').click(function () {

var content=$('#chat_send').val();

? ? ? ? ? ? var str=id+'說:'+content;

? ? ? ? ? ? var data={'id':id,'content':str}

data=JSON.stringify(data);

? ? ? ? ? ? ws.send(data);

? ? ? ? ? ? $('#chat_room').append('<p>您說:'+content+'</p>');

? ? ? ? ? ? $('#chat_send').val('')

})

$("#chat_send").keypress(function (e) {

if (e.which ==13) {

var content=$('#chat_send').val();

? ? ? ? ? ? ? ? var str=id+'說:'+content;

? ? ? ? ? ? ? ? var data={'id':id,'content':str}

var $chatRoom =$('#chat_room')

data=JSON.stringify(data);

? ? ? ? ? ? ? ? ws.send(data);

? ? ? ? ? ? ? ? $('#chat_room').append('<p>您說:'+content+'</p>')

$('#chat_send').val('')

$chatRoom[0].scrollTop = $chatRoom[0].scrollHeight-$chatRoom[0].clientHeight;

? ? ? ? ? ? }

});

? ? };

? ? ws.onmessage =function(e) {

var msg=JSON.parse(e.data);

? ? ? ? ? if(msg.status==0){

$('#chat_room').append('<p>'+msg.msg+'</p>');

? ? ? ? ? ? ? var $chatRoom =$('#chat_room')

$chatRoom[0].scrollTop = $chatRoom[0].scrollHeight-$chatRoom[0].clientHeight;

? ? ? ? ? }

};

</script>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市姐仅,隨后出現(xiàn)的幾起案子花枫,更是在濱河造成了極大的恐慌,老刑警劉巖掏膏,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劳翰,死亡現(xiàn)場離奇詭異,居然都是意外死亡馒疹,警方通過查閱死者的電腦和手機(jī)磕道,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來行冰,“玉大人溺蕉,你說我怎么就攤上這事〉孔觯” “怎么了疯特?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肛走。 經(jīng)常有香客問我漓雅,道長,這世上最難降的妖魔是什么朽色? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任邻吞,我火速辦了婚禮,結(jié)果婚禮上葫男,老公的妹妹穿的比我還像新娘抱冷。我一直安慰自己,他們只是感情好梢褐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布旺遮。 她就那樣靜靜地躺著,像睡著了一般盈咳。 火紅的嫁衣襯著肌膚如雪耿眉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天鱼响,我揣著相機(jī)與錄音鸣剪,去河邊找鬼。 笑死丈积,一個(gè)胖子當(dāng)著我的面吹牛筐骇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播桶癣,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼拥褂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了牙寞?” 一聲冷哼從身側(cè)響起饺鹃,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎间雀,沒想到半個(gè)月后悔详,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惹挟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年茄螃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片连锯。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡归苍,死狀恐怖用狱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拼弃,我是刑警寧澤夏伊,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站吻氧,受9級(jí)特大地震影響溺忧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盯孙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一鲁森、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧振惰,春花似錦歌溉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至透罢,卻和暖如春榜晦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背羽圃。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國打工乾胶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人朽寞。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓识窿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親脑融。 傳聞我的和親對象是個(gè)殘疾皇子喻频,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容