摘要:協(xié)議在年誕生,年成為國(guó)際標(biāo)準(zhǔn)。手時(shí)不容易屏蔽,能通過(guò)各種代理服務(wù)器。沒(méi)有同源限制,客戶端可以與任意服務(wù)器通信。協(xié)議標(biāo)識(shí)符是如果加密,則為,服務(wù)器網(wǎng)址就是。
WebSocket
WebSocket 協(xié)議在2008年誕生,2011年成為國(guó)際標(biāo)準(zhǔn)。所有瀏覽器都已經(jīng)支持了。
它的最大特點(diǎn)就是,服務(wù)器可以主動(dòng)向客戶端推送信息,客戶端也可以主動(dòng)向服務(wù)器發(fā)送信息,是真正的雙向平等對(duì)話,屬于服務(wù)器推送技術(shù)的一種。
為什么需要 WebSocket?需求是:用戶停留頁(yè)面 15 分鐘,且沒(méi)有任何操作,則彈出登陸窗口,讓用戶重新登陸。
一般這樣的需求實(shí)現(xiàn)多為長(zhǎng)連接輪詢,會(huì)有瀏覽器的卡頓、服務(wù)端消耗及不容易維護(hù)等問(wèn)題。
后來(lái)發(fā)現(xiàn) websocket 這樣的通訊方式,主要有以下優(yōu)點(diǎn):
建立在 TCP 協(xié)議之上,服務(wù)器端的實(shí)現(xiàn)比較容易。
手時(shí)不容易屏蔽,能通過(guò)各種 HTTP 代理服務(wù)器。
數(shù)據(jù)格式比較輕量,性能開(kāi)銷(xiāo)小,通信高效。
可以發(fā)送文本,也可以發(fā)送二進(jìn)制數(shù)據(jù)。
沒(méi)有同源限制,客戶端可以與任意服務(wù)器通信。
協(xié)議標(biāo)識(shí)符是ws(如果加密,則為wss),服務(wù)器網(wǎng)址就是 URL。
目標(biāo)已經(jīng)選定,那么如何實(shí)現(xiàn)呢?
PHP 已經(jīng)有非常好用的異步網(wǎng)絡(luò)通信框架 swoole,節(jié)省了自己實(shí)現(xiàn) websocket 服務(wù)的時(shí)間。我的使用的是 laravel 框架,最終選擇了 laravel-swoole 擴(kuò)展。
安裝配置引入 laravel-swoole 擴(kuò)展包 wiki 。啟用 websocket.enabled 及其他相應(yīng)的配置,通過(guò)下面的命名可以非常方便的管理服務(wù):
php artisan swoole:http {start|stop|restart|reload|infos}
修改配置文件中的默認(rèn) handler 配置為自定義的類(lèi):主要是為了自定義 websocket 的生命周期中的一些回調(diào)。
/* |-------------------------------------------------------------------------- | Websocket handler for onOpen and onClose callback | Replace this handler if you want to customize your websocket handler |-------------------------------------------------------------------------- */ "handler" => AppListenersSwooleWebsocketHandler::class, /* |-------------------------------------------------------------------------- | Default frame parser | Replace it if you want to customize your websocket payload |-------------------------------------------------------------------------- */ "parser" => SwooleTWHttpWebsocketSocketIOSocketIOParser::class,
當(dāng)配置完成后,會(huì)在 routes 目錄中添加一個(gè)名為 websocket.php 的文件。可以非常方便像定義 laravel 路由一樣,定義各種事件。例如:
//Websocket::on("open", function ($websocket, Request $request) { // Log::info("websocket","open 111 +" . $websocket->getSender()); //}); // //Websocket::on("connect", function ($websocket, Request $request) { // Log::info("websocket","Connected ++ 222" . $websocket->getSender()); // // called while socket on connect. //}); // //Websocket::on("disconnect", function ($websocket) { // Log::info("websocket","Disconnected ++ 333" . $websocket->getSender()); // // called while socket on disconnect //}); // 在 UserController 中的 checkLogin 方法上會(huì)帶有$websocket, $data這兩個(gè)參數(shù)。 Websocket::on("loginCheck", "AppHttpControllersApiUserController@checkLogin"); Websocket::on("logout", "AppHttpControllersApiUserController@sendLogout");使用 控制器:
public function checkLogin($websocket, $data) { if (empty($data["holding"])) { $websocket->emit("message", ["code" => self::HTTP_UNPROCESSABLE_ENTITY, "message" => "參數(shù)錯(cuò)誤"]); return false; } $flag = true; $step = 1; while ($flag) { $step++; if ( ! $this->validateLoginStatus($data["holding"])) { $websocket->emit("message", ["code" => self::HTTP_UNAUTHORIZED, "message" => "登陸超時(shí)"]); unset($step); $flag = false; }else { if($step === 1) { $websocket->emit("message", ["code" => self::HTTP_OK, "message" => "success"]); } } sleep(1); } }前端調(diào)用
這里一定要注意數(shù)據(jù)包的結(jié)構(gòu),之前就踩了比較多的坑,API docs 才找到正確的結(jié)構(gòu):
var websocket = new WebSocket("ws://127.0.0.1:1215"); websocket.onopen = function (evt) { console.log("已連接websocket服務(wù)器"); // 這里比較關(guān)鍵,通道建立后,可以進(jìn)非常方便的進(jìn)行輪詢 setInterval(function() { if (websocket.bufferedAmount == 0) var data = {"holding": "eyJLQNDqj0y473pCJ6zjMTUyOTk5NzU1MgnVMQ==$d84XkeMCv7umajhMRiU"}; websocket.send(encodeMessage("loginCheck", data)); }, 50); }; // 監(jiān)聽(tīng)消息體 websocket.onmessage = function (evt) { console.log(decodeMessage(evt.data)) }; // 監(jiān)聽(tīng)關(guān)閉消息 websocket.onclose = function (evt) { console.log("websocket close"); }; //監(jiān)聽(tīng)連接錯(cuò)誤信息 websocket.onerror = function (evt) { console.log(evt); }; function decodeMessage(str) { return JSON.parse(str.substring(2))[1] || []; } function encodeMessage(event, data) { return JSON.stringify([ event, data ]) }Swoole擴(kuò)展安裝
因?yàn)?swoole 的安裝依賴 php 的 sockets 模塊的開(kāi)啟。
安裝 swoole
中間報(bào)錯(cuò),需要安裝以下依賴:
yum -y install gcc postgresql-devel gcc-c++
下載 swoole 擴(kuò)展源碼,安裝 安裝步驟 進(jìn)行安裝即可。
性能監(jiān)控查看當(dāng)前
$ netstat -n | awk "/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}" TIME_WAIT 814 CLOSE_WAIT 1 FIN_WAIT1 1 ESTABLISHED 634 SYN_RECV 2 LAST_ACK 1
常用的三個(gè)狀態(tài)是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主動(dòng)關(guān)閉,CLOSE_WAIT 表示被動(dòng)關(guān)閉。
刪除進(jìn)程查看進(jìn)程數(shù)
$ ps -eaf |grep "swoole" | grep -v "grep"| awk "{print $2}"|wc -l
批量刪除進(jìn)程:
$ ps -eaf |grep "swoole" | grep -v "grep"| awk "{print $2}"|xargs kill -9
重啟服務(wù)。
參考文章阮一峰WebSocket教程
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/106904.html
摘要:早期的輪詢是通過(guò)不斷自動(dòng)刷新頁(yè)面而實(shí)現(xiàn)的。長(zhǎng)輪詢的另一個(gè)問(wèn)題是缺乏標(biāo)準(zhǔn)實(shí)現(xiàn)。服務(wù)器端接到這個(gè)請(qǐng)求后作出回應(yīng)并不斷更新連接狀態(tài)以保證客戶端和服務(wù)器端的連接不過(guò)期。協(xié)議解析協(xié)議包含兩部分一部分是握手,一部分是數(shù)據(jù)傳輸。 Websocket是什么? Websocket是一個(gè)因?yàn)閼?yīng)用場(chǎng)景越來(lái)越復(fù)雜而提出的,針對(duì)瀏覽器和web服務(wù)器之間雙向持續(xù)通信而設(shè)計(jì),而且優(yōu)雅地兼容HTTP的協(xié)議(我猜想:同...
摘要:那么,是否就無(wú)法用來(lái)開(kāi)發(fā)雙向通信的應(yīng)用呢答案是否定的。內(nèi)置通信支持,可以與程序基于進(jìn)行雙向通信。通信協(xié)議于年被定為標(biāo)準(zhǔn),并由補(bǔ)充規(guī)范。前言 眾所周知,PHP用于開(kāi)發(fā)基于HTTP協(xié)議的網(wǎng)站應(yīng)用非常便捷。而HTTP協(xié)議是一種單向的通信協(xié)議,只能接收客戶端的請(qǐng)求,然后響應(yīng)請(qǐng)求,不能主動(dòng)向客戶端推送信息。因此,一些實(shí)時(shí)性要求比較高的應(yīng)用,如實(shí)時(shí)聊天、直播應(yīng)用、在線網(wǎng)頁(yè)游戲等,就不適合采用HTTP協(xié)議...
摘要:那么,是否就無(wú)法用來(lái)開(kāi)發(fā)雙向通信的應(yīng)用呢答案是否定的。內(nèi)置通信支持,可以與程序基于進(jìn)行雙向通信。通信協(xié)議于年被定為標(biāo)準(zhǔn),并由補(bǔ)充規(guī)范。前言 眾所周知,PHP用于開(kāi)發(fā)基于HTTP協(xié)議的網(wǎng)站應(yīng)用非常便捷。而HTTP協(xié)議是一種單向的通信協(xié)議,只能接收客戶端的請(qǐng)求,然后響應(yīng)請(qǐng)求,不能主動(dòng)向客戶端推送信息。因此,一些實(shí)時(shí)性要求比較高的應(yīng)用,如實(shí)時(shí)聊天、直播應(yīng)用、在線網(wǎng)頁(yè)游戲等,就不適合采用HTTP協(xié)議...
摘要:是一個(gè)請(qǐng)求對(duì)象,包含了客戶端發(fā)來(lái)的握手請(qǐng)求信息事件函數(shù)中可以調(diào)用向客戶端發(fā)送數(shù)據(jù)或者調(diào)用關(guān)閉連接事件回調(diào)是可選的當(dāng)服務(wù)器收到來(lái)自客戶端的數(shù)據(jù)幀時(shí)會(huì)回調(diào)此函數(shù)。 前言:了解概念之后就應(yīng)該練練手啦,不然就是巨嬰 有收獲的話請(qǐng)加顆小星星,沒(méi)有收獲的話可以 反對(duì) 沒(méi)有幫助 舉報(bào)三連 代碼倉(cāng)庫(kù) 實(shí)戰(zhàn)swoole【聊天室】 在線體驗(yàn) 準(zhǔn)備工作 需要先看初識(shí)swoole【上】,了解基本的服務(wù)端...
摘要:進(jìn)程可以使用函數(shù)向進(jìn)程投遞新的任務(wù)。當(dāng)前的進(jìn)程在調(diào)用回調(diào)函數(shù)時(shí)會(huì)將進(jìn)程狀態(tài)切換為忙碌,這時(shí)將不再接收新的,當(dāng)函數(shù)返回時(shí)會(huì)將進(jìn)程狀態(tài)切換為空閑然后繼續(xù)接收新的。當(dāng)進(jìn)程投遞的任務(wù)在中完成時(shí),進(jìn)程會(huì)通過(guò)方法將任務(wù)處理的結(jié)果發(fā)送給進(jìn)程。 swoole——從入門(mén)到放棄(一) 一、swoole的源碼包安裝 下載swoole源碼:git clone https://gitee.com/swoole...
閱讀 2398·2021-11-23 09:51
閱讀 1209·2021-11-22 13:54
閱讀 3422·2021-09-24 10:31
閱讀 1066·2021-08-16 10:46
閱讀 3619·2019-08-30 15:54
閱讀 700·2019-08-30 15:54
閱讀 2886·2019-08-29 17:17
閱讀 3154·2019-08-29 15:08