摘要:初始化發(fā)送消息判斷用戶是否登錄如果沒(méi)有登錄拒絕連接斷開(kāi)清除信息處理協(xié)議主要是方法,輪訓(xùn)獲取消息。
這個(gè)列子主要討論Tcp,WebSocket和http之間的通訊。長(zhǎng)連接和長(zhǎng)連接通訊,長(zhǎng)連接和短連接通訊。其他協(xié)議同理可得
Tcp: 代表硬件設(shè)備 WebSocket: 代表客戶端 http: 代表網(wǎng)頁(yè)
本列子是基于one框架 (https://github.com/lizhichao/one) 開(kāi)發(fā).
配置協(xié)議 監(jiān)聽(tīng)端口由于swoole的模型 WebSocket server 包含 http server , http server 包含 tcp server 。
所以我們配置主服務(wù)為 WebSocket server ,添加兩個(gè)http 和 tcp 監(jiān)聽(tīng)。配置文件如下:
return [ "server" => [ "server_type" => OneSwooleOneServer::SWOOLE_WEBSOCKET_SERVER, "port" => 8082, "action" => AppTestMixProWs::class, "mode" => SWOOLE_PROCESS, "sock_type" => SWOOLE_SOCK_TCP, "ip" => "0.0.0.0", "set" => [ "worker_num" => 5 ] ], "add_listener" => [ // http 監(jiān)聽(tīng) [ "port" => 8081, "action" => AppServerAppHttpPort::class, "type" => SWOOLE_SOCK_TCP, "ip" => "0.0.0.0", "set" => [ "open_http_protocol" => true, "open_websocket_protocol" => false ] ], // tcp 監(jiān)聽(tīng) [ "port" => 8083, "pack_protocol" => OneProtocolText::class, // tcp 打包,解包協(xié)議,方便在終端調(diào)試 我們使用 text 協(xié)議. 換行符 表示一個(gè)包的結(jié)束 "action" => AppTestMixProTcpPort::class, "type" => SWOOLE_SOCK_TCP, "ip" => "0.0.0.0", "set" => [ "open_http_protocol" => false, "open_websocket_protocol" => false ] ] ] ];
接下來(lái)去 AppTestMixProWs 和 AppTestMixProTcpPort 實(shí)現(xiàn)各種事件處理。
AppServerAppHttpPort 是框架內(nèi)置的,通過(guò)路由處理http請(qǐng)求的,配置路由即可。
// 首頁(yè) Router::get("/mix", [ "use" => HttpController::class . "@index", "middle" => [AppTestMixProTestMiddle::class . "@isLogin"] // 中間件 如果用戶登錄了 直接跳轉(zhuǎn)到相應(yīng)的頁(yè)面 ]); Router::group([ "middle" => [AppTestMixProTestMiddle::class . "@checkSession"] // 中間件 讓用戶登錄后 才能進(jìn)入聊天頁(yè)面 http websocket 都能獲取到這個(gè) session ], function () { // websocket 頁(yè)面 Router::get("/mix/ws", HttpController::class . "@ws"); // http 頁(yè)面 Router::get("/mix/http", HttpController::class . "@http"); // http 輪訓(xùn)消息接口 Router::post("/mix/http/loop", HttpController::class . "@httpLoop"); // http 發(fā)送消息接口 Router::post("/mix/http/send", HttpController::class . "@httpSend"); });
配置的都是 http 協(xié)議路由。 websocket和tpc我們直接在回調(diào)action處理。如果你的項(xiàng)目復(fù)雜也可以配置相應(yīng)的路由。one框架的路由支持任何協(xié)議,使用方法也是統(tǒng)一的。
處理tcp協(xié)議其中__construct,onConnect,onClose 不是必須的。
如果你想在服務(wù)器運(yùn)行開(kāi)始時(shí)最一些事情就寫到 __construct里面。
onConnect 當(dāng)有客戶端連接時(shí)觸發(fā),每個(gè)客戶端觸發(fā)一次
onClose 當(dāng)有客戶端連接斷開(kāi)時(shí)觸發(fā),每個(gè)客戶端觸發(fā)一次
class TcpPort extends Tcp { use Funs; private $users = []; /** * @var Ws */ protected $server; /** * @var Client */ protected $global_data; public function __construct($server, $conf) { parent::__construct($server, $conf); $this->global_data = $this->server->global_data; } // 終端連接上服務(wù)器時(shí) public function onConnect(swoole_server $server, $fd, $reactor_id) { $name = uuid(); $this->users[$fd] = $name; $this->sendTo("all", json_encode(["v" => 1, "n" => $name])); $this->sendToTcp($fd, json_encode(["v" => 4, "n" => $this->getAllName()])); $this->global_data->bindId($fd, $name); $this->send($fd, "你的名字是:" . $name); } // 消息處理 像某個(gè)name 發(fā)送消息 public function onReceive(swoole_server $server, $fd, $reactor_id, $data) { $arr = explode(" ", $data); if (count($arr) !== 3 || $arr[0] !== "send") { $this->send($fd, "格式不正確"); return false; } $n = $arr[1]; $d = $arr[2]; $this->sendTo($n, json_encode(["v" => 3, "n" => $d])); } // 下線 通知所有其他終端,解除與fd的關(guān)系綁定。 public function onClose(swoole_server $server, $fd, $reactor_id) { echo "tcp close {$fd} "; $this->global_data->unBindFd($fd); $this->sendTo("all", json_encode(["v" => 2, "n" => $this->users[$fd]])); unset($this->users[$fd]); } }
定義了一個(gè)公共的traitFuns主要實(shí)現(xiàn)兩個(gè)方法,獲取所有的終端(tcp,ws,http),和向某個(gè)用戶發(fā)送消息 。在ws、http都會(huì)用到這個(gè)
在構(gòu)造函數(shù)我們初始化了一個(gè) global_data 用來(lái)保存,名稱和fd的關(guān)系。你也可以使用方式儲(chǔ)存。因?yàn)閒d沒(méi)次連接都不同。global_data是one框架內(nèi)置的。
終端連接上服務(wù)器時(shí)觸發(fā)事件 onConnect ,我們給這個(gè)終端取個(gè)名字,并把關(guān)系保存在 global_data。 通知所有終端有個(gè)新終端加入,并告訴剛加入的終端當(dāng)前有哪些終端在線。
其中__construct,onHandShake,onOpen,onClose 不是必須的。
onHandShake,onOpen 是配合使用的,如果onOpen返回false服務(wù)器會(huì)拒絕連接。
在 onOpen,onMessage,onClose可以拿到當(dāng)前用戶的session信息和http是相通的。
class Ws extends WsServer { use Funs; private $users = []; /** * @var Client */ public $global_data = null; public function __construct(swoole_server $server, array $conf) { parent::__construct($server, $conf); $this->global_data = new Client(); } // 初始化session public function onHandShake(swoole_http_request $request, swoole_http_response $response) { return parent::onHandShake($request, $response); } // ws 發(fā)送消息 public function onMessage(swoole_websocket_server $server, swoole_websocket_frame $frame) { $data = $frame->data; $arr = json_decode($data, true); $n = $arr["n"]; $d = $arr["d"]; $this->sendTo($n, json_encode(["v" => 3, "n" => $d])); } // 判斷用戶是否登錄 如果沒(méi)有登錄拒絕連接 public function onOpen(swoole_websocket_server $server, swoole_http_request $request) { $name = $this->session[$request->fd]->get("name"); if ($name) { $this->users[$request->fd] = $name; $this->sendTo("all", json_encode(["v" => 1, "n" => $name])); $this->global_data->bindId($request->fd, $name); return true; } else { return false; } } // ws 斷開(kāi)清除信息 public function onClose(swoole_server $server, $fd, $reactor_id) { echo "ws close {$fd} "; $this->global_data->unBindFd($fd); $this->sendTo("all", json_encode(["v" => 2, "n" => $this->users[$fd]])); unset($this->users[$fd]); } }處理 http 協(xié)議
主要是 httpLoop 方法,輪訓(xùn)獲取消息。因?yàn)閔ttp是短連接,發(fā)給http的信息我們是先存放在$global_data,然后直接這里讀取。防止連接間隙丟信息。
class HttpController extends Controller { use Funs; /** * @var Ws */ protected $server; /** * @var Client */ protected $global_data; public function __construct($request, $response, $server = null) { parent::__construct($request, $response, $server); $this->global_data = $this->server->global_data; } /** * 首頁(yè) */ public function index() { $code = sha1(uuid()); $this->session()->set("code", $code); return $this->display("index", ["code" => $code]); } /** * ws頁(yè)面 */ public function ws() { $name = $this->session()->get("name"); if (!$name) { $name = uuid(); $this->session()->set("name", $name); } return $this->display("ws",["users" => $this->getAllName(),"name" => $name]); } /** * http 頁(yè)面 */ public function http() { $name = $this->session()->get("name"); if (!$name) { $name = uuid(); $this->session()->set("name", $name); } $this->global_data->set("http.{$name}", 1, time() + 60); $this->sendTo("all", json_encode(["v" => 1, "n" => $name])); return $this->display("http", ["list" => $this->getAllName(), "name" => $name]); } /** * http輪訓(xùn) */ public function httpLoop() { $name = $this->session()->get("name"); $this->global_data->set("http.{$name}", 1, time() + 60); $i = 0; do { $data = $this->global_data->getAndDel("data.{$name}"); $i++; co::sleep(0.1); } while ($data === null && $i < 300); if ($data) { foreach ($data as &$v) { $v = json_decode($v, true); } } else { $data = []; } return $this->json($data); } /** * http發(fā)送消息 */ public function httpSend() { $n = $this->request->post("n"); $d = $this->request->post("d"); if ($n && $d) { $this->sendTo($n, json_encode(["v" => 3, "n" => $d])); return "1"; } return "0"; } public function __destruct() { } public function __call($name, $arguments) { return $this->server->$name(...$arguments); } }
到此基本就完成了。你可以去看完整的代碼 : 點(diǎn)這里
其他的一些列子 : https://github.com/lizhichao/...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/31219.html
摘要:而要實(shí)現(xiàn)物物相連,一共有個(gè)階段性任務(wù),而這個(gè)階段性任務(wù),也伴隨著巨大的挑戰(zhàn)本文分享自華為云社區(qū)云駐共創(chuàng)以小窺大,從一盞路燈看億萬(wàn)物聯(lián)網(wǎng)之路云駐共創(chuàng)以小窺大,從一盞路燈看億萬(wàn)物聯(lián)網(wǎng)之路,作者啟明。 摘要:IoT, Internet of Things,物聯(lián)網(wǎng),顧名思義,是物物相連。而要實(shí)現(xiàn)物...
摘要:去年月,阿里云宣布將設(shè)立阿里云廣東研發(fā)中心,招募名云計(jì)算和人工智能工程師,推動(dòng)前沿技術(shù)與廣東產(chǎn)業(yè)融合。吳維剛表示,人工智能與云計(jì)算,兩者不是同一事物,但是相互發(fā)展。近年來(lái),隨著互聯(lián)網(wǎng)和移動(dòng)互聯(lián)網(wǎng)的蓬勃發(fā)展,大數(shù)據(jù)、云計(jì)算、人工智能、物聯(lián)網(wǎng)等新技術(shù)也迎來(lái)了廣闊的發(fā)展空間。去年,阿里云工業(yè)互聯(lián)網(wǎng)全國(guó)總部正式在廣州揭牌成立,阿里云將聯(lián)合廣東本地合作伙伴,共同打造服務(wù)全國(guó)的工業(yè)大腦。去年9月,華為與...
摘要:通過(guò)通信線路連入通信子網(wǎng)終端是用戶訪問(wèn)網(wǎng)絡(luò)的界面網(wǎng)絡(luò)操作系統(tǒng)是相對(duì)于主機(jī)操作系統(tǒng)而言的。接收方使用同一擴(kuò)頻碼進(jìn)行擴(kuò)解。 目錄 一、計(jì)算機(jī)網(wǎng)絡(luò) 1.計(jì)算機(jī)網(wǎng)絡(luò)技術(shù)概述 2.計(jì)算機(jī)網(wǎng)絡(luò)分類 3.無(wú)線網(wǎng)絡(luò)分類 二、無(wú)線通信和網(wǎng)絡(luò)仿真技術(shù)基礎(chǔ) 1.基本概念 2.調(diào)制 (1)、概述 (2)、常用方式 ...
摘要:一個(gè)輕量級(jí)高效率的支持聊天與物聯(lián)網(wǎng)的通訊框架從月初到現(xiàn)在已經(jīng)大約已經(jīng)三個(gè)月了,由于一直沒(méi)有時(shí)間與精力很好的維護(hù)這個(gè)項(xiàng)目,心里一直有所歉意。希望本項(xiàng)目對(duì)你有所幫助,我的目標(biāo)暫定,一個(gè)小眾加物聯(lián)網(wǎng)的開(kāi)源通訊項(xiàng)目。 篇幅較長(zhǎng),感謝閱讀。 萬(wàn)事開(kāi)頭難 在我決定做開(kāi)源是因?yàn)樽陨砉ぷ鹘佑|到大多數(shù)的項(xiàng)目都是基于開(kāi)源大佬寫的框架,自覺(jué)慚愧,工作以來(lái)一直忙于業(yè)務(wù)與功能實(shí)現(xiàn),多多少少做過(guò)的幾個(gè)項(xiàng)目也沒(méi)能抽...
閱讀 2530·2021-08-11 11:16
閱讀 2957·2019-08-30 15:55
閱讀 3356·2019-08-30 12:53
閱讀 1603·2019-08-29 13:28
閱讀 3288·2019-08-28 18:17
閱讀 968·2019-08-26 12:19
閱讀 2493·2019-08-23 18:27
閱讀 738·2019-08-23 18:17