對接IOT的amqp的時候,已經建立正常連接。如下:
問題: 在進行多次數(shù)據(jù)包的傳送后, 云平臺的數(shù)據(jù)包接收 出現(xiàn) 不完整的情況。導致出現(xiàn):unknown cmd MESSAGE
報錯。
代碼位置stomp包下的Client
類的onConnectionMessage
方法
進一步排查TcpConnection
下第557行public function baseRead($socket, $check_eof = true)
方法處理數(shù)據(jù)包可能有問題。
因為前幾次包的數(shù)據(jù)解析正常,后面就一直不對了。
包的長度是在 vendor/workerman/stomp/src/Protocols/Stomp.php
里的input方法計算的,看下這里是不是有什么問題,返回的長度不一致。
老大, 我在TcpConnection
類下baseRead
方法下,if ($this->_currentPackageLength === 0) { break; }
方法體內部追加 $this->_recvBuffer = '';
作用是修復因Remove the current package from the receive buffer后, 接收下次數(shù)據(jù)包的時候 ( $this->_recvBuffer .= $buffer;) 導致數(shù)據(jù)包長度不一致。
$this->_recvBuffer .= $buffer;
原因就是recvBuffer 會拼接每次的新數(shù)據(jù)包,而當$this->_currentPackageLength
為0 的時候,沒有clean 這個 $this->_recvBuffe
.
應該不是workerman的問題。$this->_currentPackageLength
為0,說明當前包的數(shù)據(jù)不夠,無法計算包長,繼續(xù)等待數(shù)據(jù)。數(shù)據(jù)不夠肯定不能將已經收到的數(shù)據(jù)清零的,那樣就丟包了。
stomp包的長度是在 vendor/workerman/stomp/src/Protocols/Stomp.php
里的input方法計算的,如果你每個包的長度都一樣,但是$this->_currentPackageLength,應該在input方法里找原因
首先,包上這樣的`$buffer = 'MESSAGE
qos:1
destination:/a1pyomK5esO//user/update
message-id:1524185981254223361
topic:/a1pyomK5esO//user/update
subscription:client-1
generateTime:1652229230594
{"breathe":"0","heartbeat":"0","onbed":"0","fanshen":"0","pressure":"0","deviation":"193"}' . "\0" . '' . "\0" . ''; 從buffer中 get full package后,余下的buffer 不夠input方法計算,返回
$this->_currentPackageLength為0, 如果不添加
$this->_recvBuffer = '', 繼續(xù)等待數(shù)據(jù)。等來下一次新的數(shù)據(jù)包發(fā)來的時候,
$this->_recvBuffer .= $buffer;會拼接上一次余下的buffer,導致包的數(shù)據(jù)就不對了。然后 input 方法計算后的的長度,給
$one_request_buffer = \substr($this->_recvBuffer, 0, $this->_currentPackageLength);` 得到數(shù)據(jù)就是錯誤的。
老大 我建議將 input 下的 $end_pos = strpos($buffer, "\x00");
換成 $end_pos = strripos($buffer, "\x00");