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