@敖德薩
1)用戶端建立websocket通信
2)硬件端建立tcp通信
3)通過$_SERVER['REMOTE_PORT']和$_SERVER['REMOTE_ADDR']來區(qū)分過來的數(shù)據(jù)
4)每個(gè)端數(shù)據(jù)中傳一個(gè)相同參數(shù)作為互推依據(jù)。
可以給個(gè)具體方案嗎?你說通過$_SERVER['REMOTE_PORT']和$_SERVER['REMOTE_ADDR']來區(qū)分發(fā)過來的數(shù)據(jù) 那么問題來了 我在哪里接收?onmessge? onmessge怎樣接收tcp協(xié)議發(fā)過來的數(shù)據(jù)?這個(gè)也是現(xiàn)在困擾我的問題 所以你說了這么多 我還沒看到有希望的信息 能給個(gè)具體的信息嗎
@7269: 我沒有用walkor給我的方法 因?yàn)槲覍懲炅藈alkor才給上面的方法 我也還沒有去驗(yàn)證 不過我的方法我已經(jīng)分享到workerman官方10群里了
用戶(13969)在手機(jī)上發(fā)送指令(02 03 05 d5 aa 52 d5)給服務(wù)器,通過服務(wù)器再發(fā)送給dtu設(shè)備,dtu設(shè)備(2002)向服務(wù)器返回一個(gè)指令(02 03 05 d5 aa 52 d5),服務(wù)器收到指令后,我想通過sendtouid()發(fā)送給用戶,告知用戶設(shè)備正??梢允褂???墒怯脩舻膗id我沒法獲取。這個(gè)你怎么處理的?
GatewayWorker所有的數(shù)據(jù)通過Events.php里的onMessage來接收。
gatewayWorker支持多協(xié)議,如果增加一個(gè)協(xié)議只需要開一個(gè)端口設(shè)置對應(yīng)的端口參數(shù)及協(xié)議即可。協(xié)議層對于開發(fā)者來說是透明的。也就是說調(diào)用所有的gatewayWorker 的 Gateway::XXX(如Gateway::bindUid Gateway::sendToUid)接口時(shí),不需要考慮對應(yīng)客戶端是什么協(xié)議,直接調(diào)用即可。
如何設(shè)置多個(gè)協(xié)議,參考http://doc2.workerman.net/multi-protocols.html
現(xiàn)在假設(shè)你設(shè)置了tcp協(xié)議和websocket協(xié)議。那么整個(gè)系統(tǒng)代碼及流程類似這樣
1)、硬件客戶端通過tcp向GatewayWorker發(fā)送一個(gè)數(shù)據(jù)包,包中包含了{(lán)請求類型:設(shè)備綁定, 設(shè)備id:設(shè)備具體id}(數(shù)據(jù)格式任意,這里是一個(gè)示意),GatewayWorker收到數(shù)據(jù)后,Events.php里的onMessage接收整個(gè)數(shù)據(jù),發(fā)現(xiàn)是設(shè)備綁定類型,然后調(diào)用Gateway::bindUid($client_id, '具體的設(shè)備id');
,這樣就將設(shè)備于具體的設(shè)備id綁定了,在Events.php中調(diào)用Gateway::sendToUid('具體的設(shè)備id', '數(shù)據(jù)');
就可以給這個(gè)設(shè)備發(fā)數(shù)據(jù)了。
2)、同樣的用戶端通過websocket發(fā)起連接,然后發(fā)送一個(gè){請求類型:用戶綁定, 用戶id:用戶具體id}請求給GatewayWorker,Events.php里的onMessage接收整個(gè)數(shù)據(jù),發(fā)現(xiàn)是用戶綁定類型,然后調(diào)用Gateway::bindUid($client_id, '具體的用戶id');
,這樣就將用戶端與具體的用戶id綁定了,在Events.php中調(diào)用Gateway::sendToUid('具體用戶id', '數(shù)據(jù)');
就可以給這個(gè)用戶發(fā)數(shù)據(jù)了。
假設(shè)你上面的設(shè)備及用戶綁定已經(jīng)做好,現(xiàn)在說說你的圖中1 2 3 4 5 6的代碼及流程
1、設(shè)備發(fā)起tcp請求
假設(shè)請求數(shù)據(jù)格式為 {type: getData}
2、GatewayWorker收到tcp請求后返回該設(shè)備相關(guān)數(shù)據(jù)
給當(dāng)前設(shè)備返回?cái)?shù)據(jù),直接調(diào)用 Gateway::sendToClient($client_id, '數(shù)據(jù)');
即可。
3、用戶通過websocket發(fā)送開關(guān)指令
假設(shè)數(shù)據(jù)格式為 {type: opertation, operation: close, device_id:具體設(shè)備id}
4、服務(wù)端收到指令后發(fā)給設(shè)備
Events.php里onMessage里利用Gateway::sendToUid(具體設(shè)備id, '設(shè)備能識別的關(guān)閉數(shù)據(jù)');
給對應(yīng)設(shè)備發(fā)送操作
5、設(shè)備返回成功或失敗
數(shù)據(jù)包假設(shè)格式為{type: opertation_result, result: success},同樣的Events.php里onMessage里接收這個(gè)數(shù)據(jù)
6、將成功或者失敗結(jié)果轉(zhuǎn)發(fā)給用戶
Events.php里onMessage里利用Gateway::sendToUid(具體用戶id, '結(jié)果數(shù)據(jù)');
給對應(yīng)的用戶id
總的來說Events.php里代碼類似這樣。
假設(shè)設(shè)備和用戶發(fā)來的數(shù)據(jù)都是json數(shù)據(jù),代碼類似這樣
class Events {
public static function onMessage ($client_id, $data)
{
$data = json_decode($data);
switch ($data['type']) {
// {type:device_bind, device_id:具體的設(shè)備id}
case 'device_bind':
Gateway::bindUid($client_id, $data['device_id']);
// 通過數(shù)據(jù)庫或則某種方式查詢出當(dāng)前設(shè)備屬于哪個(gè)用戶,并記錄到session方便后面直接使用
$user_id = your_find_user_function($data['device_id']);
$_SESSION['belong'] = $user_id;
break;
// {type:device_bind, user_id:具體的用戶id}
case 'user_bind':
Gateway::bindUid($client_id, $data['user_id']);
break;
case 'getData':
$getDataResult = '結(jié)果數(shù)據(jù)'; // 這里假設(shè)獲得了結(jié)果
Gateway::sendToClient($client_id, $getDataResult);
break;
// {type: opertation, operation: close, device_id:具體設(shè)備id}
case 'operation':
Gateway::sendToUid($data['device_id'], "{type: opertation, operation: close}");
break;
// {type: opertation_result, result: success}
case 'opertation_result':
// 之前在sessin中記錄了當(dāng)前設(shè)備屬于哪個(gè)用戶
$user_id = $_SESSION['belong'];
// 給這個(gè)用戶發(fā)送結(jié)果
Gateway::sendToUid($uiser_id, "{type: opertation_result, result: success}");
break;
}
}
}
你好,你說:硬件客戶端通過tcp向GatewayWorker發(fā)送一個(gè)數(shù)據(jù)包,包中包含了{(lán)請求類型:設(shè)備綁定, 設(shè)備id:設(shè)備具體id}(數(shù)據(jù)格式任意,這里是一個(gè)示意)。用戶(13969)在手機(jī)上發(fā)送指令(02 03 05 d5 aa 52 d5)給服務(wù)器,通過服務(wù)器再發(fā)送給dtu設(shè)備,dtu設(shè)備(2002)向服務(wù)器返回一個(gè)指令(02 03 05 d5 aa 52 d5),服務(wù)器收到指令后,我想通過sendtouid()發(fā)送給用戶,告知用戶設(shè)備正??梢允褂?。可是用戶的uid我沒法獲取。這個(gè)你怎么處理的?
不得不佩服 @walkor 在問答這方面確實(shí)做得太好了!解答很清楚,甚至有時(shí)直接給出代碼。今天也開始從swoole轉(zhuǎn)入webman了!上手快!有點(diǎn)相見恨晚的感覺!
本人也有硬件與用戶的通訊操作,提供參考:
數(shù)據(jù)還是用redis+mysql的形式(websocket僅僅作為轉(zhuǎn)發(fā),請求全部走h(yuǎn)ttp)
采用先http后websocket的方式,由http先對訪問進(jìn)行先認(rèn)證后返回帶有websocket連接參數(shù)的頁面(連接websocket的信息包含uid在內(nèi)的一切),認(rèn)證不成立不返回websocket的頁面。
這樣方式用起來比較爽,回歸傳統(tǒng)的http收到請求,處理后通過GatewayWorker的websocket進(jìn)行通知,避免了三方操作
樓主,你看看 https://github.com/mouyong/laravel-octane-workerman 的截圖。里邊直接是給了完成通訊的截圖示例。
在 laravel 項(xiàng)目引入后,配置好相關(guān)端口。通過一行命令讓他們具備通訊支持。 php artisan workerman:gateway
。
然后按照老大的說明,直接玩就可以了。